Version 2.6.0-dev.2.0

Merge commit '2b4a84efd01e0d1cab8d00152bd8dee25aae4270' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8574697..e6efa0d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,8 +4,25 @@
 
 ### Language
 
+*   **Breaking change** [#37985](https://github.com/dart-lang/sdk/issues/37985):
+    Inference is changed when using `Null` values in a `FutureOr` context.
+    Namely, constraints of the forms similar to `Null` <: `FutureOr<T>` now
+    yield `Null` as the solution for `T`.  For example, the following code will
+    now print "Null", and it was printing "dynamic" before (note that the
+    anonymous closure `() {}` in the example has `Null` as its return type):
+
+```dart
+import 'dart:async';
+void foo<T>(FutureOr<T> Function() f) { print(T); }
+main() { foo(() {}); }
+```
+
+
 ### Core libraries
 
+* Default values of parameters of abstract methods are no longer available
+  via `dart:mirrors`.
+
 ### Dart VM
 
 ### Tools
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 63a5b47..abfe139 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -18,6 +18,26 @@
 def is_cpp_file(path):
     return path.endswith('.cc') or path.endswith('.h')
 
+
+def _CheckNnbdSdkSync(input_api, output_api):
+    files = [git_file.LocalPath() for git_file in input_api.AffectedTextFiles()]
+    unsynchronized_files = []
+    for file in files:
+        if file.startswith('sdk/'):
+            nnbd_file = 'sdk_nnbd/' + file[4:]
+            if not nnbd_file in files:
+                unsynchronized_files.append(nnbd_file)
+    if unsynchronized_files:
+        return [
+            output_api.PresubmitPromptWarning(
+                'Changes were made to sdk/ that were not made to sdk_nnbd/\n'
+                'Please update these files as well:\n'
+                '\n'
+                '%s' % ('\n'.join(unsynchronized_files)))
+        ]
+    return []
+
+
 def _CheckFormat(input_api,
                  identification,
                  extension,
@@ -243,6 +263,7 @@
 
 def _CommonChecks(input_api, output_api):
     results = []
+    results.extend(_CheckNnbdSdkSync(input_api, output_api))
     results.extend(_CheckValidHostsInDEPS(input_api, output_api))
     results.extend(_CheckDartFormat(input_api, output_api))
     results.extend(_CheckStatusFiles(input_api, output_api))
diff --git a/WATCHLISTS b/WATCHLISTS
index 1e08225..c4d820c 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -27,6 +27,8 @@
     'dart2js': {
       'filepath': (
         '^pkg/compiler|'
+        '^sdk/lib/_internal/js_runtime|'
+        '^sdk_nnbd/lib/_internal/js_runtime|'
         '^tests/compiler/dart2js'
       )
     },
diff --git a/build/config/linux/BUILD.gn b/build/config/linux/BUILD.gn
index 0db95b7..141ea68 100644
--- a/build/config/linux/BUILD.gn
+++ b/build/config/linux/BUILD.gn
@@ -11,15 +11,13 @@
     "-lc++",
     "-lc",
     "-lm",
+    "-lpthread",
     "-lclang_rt.builtins",
     "-Wl,--exclude-libs=libc++.a",
   ]
 
   if (is_asan) {
-    ldflags += [
-      "-lpthread",
-      "-lrt",
-    ]
+    ldflags += [ "-lrt" ]
   }
 
   if (sysroot != "") {
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index 686011c..55a6571 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -172,6 +172,7 @@
     'includePedanticFixes';
 const String EDIT_REQUEST_DARTFIX_INCLUDE_REQUIRED_FIXES =
     'includeRequiredFixes';
+const String EDIT_REQUEST_DARTFIX_OUTPUT_DIR = 'outputDir';
 const String EDIT_REQUEST_FORMAT = 'edit.format';
 const String EDIT_REQUEST_FORMAT_FILE = 'file';
 const String EDIT_REQUEST_FORMAT_LINE_LENGTH = 'lineLength';
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index 46ed75f..74a1344 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>
+ *   "outputDir": optional FilePath
  * }
  *
  * Clients may not extend, implement or mix-in this class.
@@ -7979,6 +7980,8 @@
 
   List<String> _excludedFixes;
 
+  String _outputDir;
+
   /**
    * A list of the files and directories for which edits should be suggested.
    *
@@ -8066,16 +8069,36 @@
     this._excludedFixes = 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,
+   * but no previously existing files will be deleted.
+   */
+  String get outputDir => _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.
+   */
+  void set outputDir(String value) {
+    this._outputDir = value;
+  }
+
   EditDartfixParams(List<String> included,
       {List<String> includedFixes,
       bool includePedanticFixes,
       bool includeRequiredFixes,
-      List<String> excludedFixes}) {
+      List<String> excludedFixes,
+      String outputDir}) {
     this.included = included;
     this.includedFixes = includedFixes;
     this.includePedanticFixes = includePedanticFixes;
     this.includeRequiredFixes = includeRequiredFixes;
     this.excludedFixes = excludedFixes;
+    this.outputDir = outputDir;
   }
 
   factory EditDartfixParams.fromJson(
@@ -8111,11 +8134,17 @@
         excludedFixes = jsonDecoder.decodeList(jsonPath + ".excludedFixes",
             json["excludedFixes"], jsonDecoder.decodeString);
       }
+      String outputDir;
+      if (json.containsKey("outputDir")) {
+        outputDir = jsonDecoder.decodeString(
+            jsonPath + ".outputDir", json["outputDir"]);
+      }
       return new EditDartfixParams(included,
           includedFixes: includedFixes,
           includePedanticFixes: includePedanticFixes,
           includeRequiredFixes: includeRequiredFixes,
-          excludedFixes: excludedFixes);
+          excludedFixes: excludedFixes,
+          outputDir: outputDir);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "edit.dartfix params", json);
     }
@@ -8142,6 +8171,9 @@
     if (excludedFixes != null) {
       result["excludedFixes"] = excludedFixes;
     }
+    if (outputDir != null) {
+      result["outputDir"] = outputDir;
+    }
     return result;
   }
 
@@ -8163,7 +8195,8 @@
           includePedanticFixes == other.includePedanticFixes &&
           includeRequiredFixes == other.includeRequiredFixes &&
           listEqual(excludedFixes, other.excludedFixes,
-              (String a, String b) => a == b);
+              (String a, String b) => a == b) &&
+          outputDir == other.outputDir;
     }
     return false;
   }
@@ -8176,6 +8209,7 @@
     hash = JenkinsSmiHash.combine(hash, includePedanticFixes.hashCode);
     hash = JenkinsSmiHash.combine(hash, includeRequiredFixes.hashCode);
     hash = JenkinsSmiHash.combine(hash, excludedFixes.hashCode);
+    hash = JenkinsSmiHash.combine(hash, outputDir.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 }
diff --git a/pkg/analysis_server/lib/src/computer/computer_overrides.dart b/pkg/analysis_server/lib/src/computer/computer_overrides.dart
index 9bd9102..c1fbda3 100644
--- a/pkg/analysis_server/lib/src/computer/computer_overrides.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_overrides.dart
@@ -131,7 +131,7 @@
 
   List<Element> _superElements = <Element>[];
   List<Element> _interfaceElements = <Element>[];
-  Set<InterfaceType> _visited = new Set<InterfaceType>();
+  Set<ClassElement> _visited = Set<ClassElement>();
 
   _OverriddenElementsFinder(Element seed) {
     _seed = seed;
@@ -152,53 +152,57 @@
    */
   OverriddenElements find() {
     _visited.clear();
-    _addSuperOverrides(_class.type, withThisType: false);
+    _addSuperOverrides(_class, withThisType: false);
     _visited.clear();
-    _addInterfaceOverrides(_class.type, false);
+    _addInterfaceOverrides(_class, false);
     _superElements.forEach(_interfaceElements.remove);
     return new OverriddenElements(_seed, _superElements, _interfaceElements);
   }
 
-  void _addInterfaceOverrides(InterfaceType type, bool checkType) {
-    if (type == null) {
+  void _addInterfaceOverrides(ClassElement class_, bool checkType) {
+    if (class_ == null) {
       return;
     }
-    if (!_visited.add(type)) {
+    if (!_visited.add(class_)) {
       return;
     }
     // this type
     if (checkType) {
-      Element element = _lookupMember(type.element);
+      Element element = _lookupMember(class_);
       if (element != null && !_interfaceElements.contains(element)) {
         _interfaceElements.add(element);
       }
     }
     // interfaces
-    for (InterfaceType interfaceType in type.interfaces) {
-      _addInterfaceOverrides(interfaceType, true);
+    for (InterfaceType interfaceType in class_.interfaces) {
+      _addInterfaceOverrides(interfaceType.element, true);
     }
     // super
-    _addInterfaceOverrides(type.superclass, checkType);
+    _addInterfaceOverrides(class_.supertype?.element, checkType);
   }
 
-  void _addSuperOverrides(InterfaceType type, {bool withThisType = true}) {
-    if (type == null) {
+  void _addSuperOverrides(ClassElement class_, {bool withThisType = true}) {
+    if (class_ == null) {
       return;
     }
-    if (!_visited.add(type)) {
+    if (!_visited.add(class_)) {
       return;
     }
 
     if (withThisType) {
-      Element element = _lookupMember(type.element);
+      Element element = _lookupMember(class_);
       if (element != null && !_superElements.contains(element)) {
         _superElements.add(element);
       }
     }
 
-    _addSuperOverrides(type.superclass);
-    type.mixins.forEach(_addSuperOverrides);
-    type.superclassConstraints.forEach(_addSuperOverrides);
+    _addSuperOverrides(class_.supertype?.element);
+    for (var mixin_ in class_.mixins) {
+      _addSuperOverrides(mixin_.element);
+    }
+    for (var constraint in class_.superclassConstraints) {
+      _addSuperOverrides(constraint.element);
+    }
   }
 
   Element _lookupMember(ClassElement classElement) {
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 146f3a5..8b5d142 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -19,7 +19,6 @@
 import 'package:analysis_server/src/services/completion/token_details/token_detail_builder.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
-import 'package:analyzer/dart/element/element.dart' as analyzer;
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
@@ -199,46 +198,10 @@
         var analysisDriver = server.getAnalysisDriver(file);
         var session = analysisDriver.currentSession;
 
-        var fileElement = await session.getUnitElement(file);
-        var libraryPath = fileElement.element.librarySource.fullName;
-
-        var resolvedLibrary = await session.getResolvedLibrary(libraryPath);
-
-        analyzer.LibraryElement requestedLibraryElement;
-        try {
-          requestedLibraryElement = await session.getLibraryByUri(
-            library.uriStr,
-          );
-        } on ArgumentError catch (e) {
-          server.sendResponse(Response.invalidParameter(
-            request,
-            'uri',
-            'Invalid URI: ${library.uriStr}\n$e',
-          ));
-          return;
-        }
-
-        var requestedElement =
-            requestedLibraryElement.exportNamespace.get(requestedName);
-        if (requestedElement == null) {
-          server.sendResponse(Response.invalidParameter(
-            request,
-            'label',
-            'No such element: $requestedName',
-          ));
-          return;
-        }
-
         var completion = params.label;
         var builder = DartChangeBuilder(session);
-        await builder.addFileEdit(libraryPath, (builder) {
-          var result = builder.importLibraryElement(
-            targetLibrary: resolvedLibrary,
-            targetPath: libraryPath,
-            targetOffset: params.offset,
-            requestedLibrary: requestedLibraryElement,
-            requestedElement: requestedElement,
-          );
+        await builder.addFileEdit(file, (builder) {
+          var result = builder.importLibraryElement(library.uri);
           if (result.prefix != null) {
             completion = '${result.prefix}.$completion';
           }
diff --git a/pkg/analysis_server/lib/src/edit/edit_dartfix.dart b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
index fb322eb..6ba64fa 100644
--- a/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
@@ -73,7 +73,7 @@
       }
     }
     for (DartFixInfo info in fixInfo) {
-      info.setup(this, listener);
+      info.setup(this, listener, params);
     }
 
     // Validate each included file and directory.
diff --git a/pkg/analysis_server/lib/src/edit/fix/basic_fix_lint_assist_task.dart b/pkg/analysis_server/lib/src/edit/fix/basic_fix_lint_assist_task.dart
index 6d0eb32..60de435 100644
--- a/pkg/analysis_server/lib/src/edit/fix/basic_fix_lint_assist_task.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/basic_fix_lint_assist_task.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/plugin/edit/assist/assist_core.dart';
+import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/edit/fix/dartfix_listener.dart';
 import 'package:analysis_server/src/edit/fix/dartfix_registrar.dart';
 import 'package:analysis_server/src/edit/fix/fix_lint_task.dart';
@@ -47,8 +48,8 @@
     }
   }
 
-  static void preferForElementsToMapFromIterable(
-      DartFixRegistrar registrar, DartFixListener listener) {
+  static void preferForElementsToMapFromIterable(DartFixRegistrar registrar,
+      DartFixListener listener, EditDartfixParams params) {
     registrar.registerLintTask(
       Registry.ruleRegistry['prefer_for_elements_to_map_fromIterable'],
       new BasicFixLintAssistTask(
@@ -57,7 +58,9 @@
   }
 
   static void preferIfElementsToConditionalExpressions(
-      DartFixRegistrar registrar, DartFixListener listener) {
+      DartFixRegistrar registrar,
+      DartFixListener listener,
+      EditDartfixParams params) {
     registrar.registerLintTask(
       Registry.ruleRegistry['prefer_if_elements_to_conditional_expressions'],
       new BasicFixLintAssistTask(
@@ -65,8 +68,8 @@
     );
   }
 
-  static void preferIntLiterals(
-      DartFixRegistrar registrar, DartFixListener listener) {
+  static void preferIntLiterals(DartFixRegistrar registrar,
+      DartFixListener listener, EditDartfixParams params) {
     registrar.registerLintTask(
       Registry.ruleRegistry['prefer_int_literals'],
       new BasicFixLintAssistTask(
@@ -74,8 +77,8 @@
     );
   }
 
-  static void preferSpreadCollections(
-      DartFixRegistrar registrar, DartFixListener listener) {
+  static void preferSpreadCollections(DartFixRegistrar registrar,
+      DartFixListener listener, EditDartfixParams params) {
     registrar.registerLintTask(
       Registry.ruleRegistry['prefer_spread_collections'],
       new BasicFixLintAssistTask(DartAssistKind.CONVERT_TO_SPREAD, listener),
diff --git a/pkg/analysis_server/lib/src/edit/fix/basic_fix_lint_error_task.dart b/pkg/analysis_server/lib/src/edit/fix/basic_fix_lint_error_task.dart
index 2cc7b1c..8275cf0 100644
--- a/pkg/analysis_server/lib/src/edit/fix/basic_fix_lint_error_task.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/basic_fix_lint_error_task.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:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/edit/fix/dartfix_listener.dart';
 import 'package:analysis_server/src/edit/fix/dartfix_registrar.dart';
 import 'package:analysis_server/src/edit/fix/fix_lint_task.dart';
@@ -15,8 +16,8 @@
   BasicFixLintErrorTask(this.fixKind, DartFixListener listener)
       : super(listener);
 
-  static void nullClosures(
-      DartFixRegistrar registrar, DartFixListener listener) {
+  static void nullClosures(DartFixRegistrar registrar, DartFixListener listener,
+      EditDartfixParams params) {
     registrar.registerLintTask(
       Registry.ruleRegistry['null_closures'],
       new BasicFixLintErrorTask(
@@ -24,8 +25,8 @@
     );
   }
 
-  static void preferEqualForDefaultValues(
-      DartFixRegistrar registrar, DartFixListener listener) {
+  static void preferEqualForDefaultValues(DartFixRegistrar registrar,
+      DartFixListener listener, EditDartfixParams params) {
     registrar.registerLintTask(
       Registry.ruleRegistry['prefer_equal_for_default_values'],
       new BasicFixLintErrorTask(
@@ -33,16 +34,16 @@
     );
   }
 
-  static void preferIsEmpty(
-      DartFixRegistrar registrar, DartFixListener listener) {
+  static void preferIsEmpty(DartFixRegistrar registrar,
+      DartFixListener listener, EditDartfixParams params) {
     registrar.registerLintTask(
       Registry.ruleRegistry['prefer_is_empty'],
       new BasicFixLintErrorTask(DartFixKind.REPLACE_WITH_IS_EMPTY, listener),
     );
   }
 
-  static void preferIsNotEmpty(
-      DartFixRegistrar registrar, DartFixListener listener) {
+  static void preferIsNotEmpty(DartFixRegistrar registrar,
+      DartFixListener listener, EditDartfixParams params) {
     registrar.registerLintTask(
       Registry.ruleRegistry['prefer_is_not_empty'],
       new BasicFixLintErrorTask(
diff --git a/pkg/analysis_server/lib/src/edit/fix/dartfix_info.dart b/pkg/analysis_server/lib/src/edit/fix/dartfix_info.dart
index 2fa706f..987a5bc 100644
--- a/pkg/analysis_server/lib/src/edit/fix/dartfix_info.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/dartfix_info.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:analysis_server/protocol/protocol_generated.dart' show DartFix;
+import 'package:analysis_server/protocol/protocol_generated.dart'
+    show DartFix, EditDartfixParams;
 import 'package:analysis_server/src/edit/edit_dartfix.dart';
+import 'package:analysis_server/src/edit/fix/basic_fix_lint_assist_task.dart';
+import 'package:analysis_server/src/edit/fix/basic_fix_lint_error_task.dart';
 import 'package:analysis_server/src/edit/fix/dartfix_listener.dart';
 import 'package:analysis_server/src/edit/fix/dartfix_registrar.dart';
 import 'package:analysis_server/src/edit/fix/fix_error_task.dart';
 import 'package:analysis_server/src/edit/fix/non_nullable_fix.dart';
 import 'package:analysis_server/src/edit/fix/prefer_mixin_fix.dart';
-import 'package:analysis_server/src/edit/fix/basic_fix_lint_assist_task.dart';
-import 'package:analysis_server/src/edit/fix/basic_fix_lint_error_task.dart';
 
 const allFixes = <DartFixInfo>[
   //
@@ -186,7 +187,8 @@
   final bool isDefault;
   final bool isPedantic;
   final bool isRequired;
-  final void Function(DartFixRegistrar dartfix, DartFixListener listener) setup;
+  final void Function(DartFixRegistrar dartfix, DartFixListener listener,
+      EditDartfixParams params) setup;
 
   const DartFixInfo(
     this.key,
diff --git a/pkg/analysis_server/lib/src/edit/fix/fix_error_task.dart b/pkg/analysis_server/lib/src/edit/fix/fix_error_task.dart
index 97c2233..11439bc 100644
--- a/pkg/analysis_server/lib/src/edit/fix/fix_error_task.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/fix_error_task.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
+import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/edit/edit_dartfix.dart';
 import 'package:analysis_server/src/edit/fix/dartfix_listener.dart';
 import 'package:analysis_server/src/edit/fix/dartfix_registrar.dart';
@@ -62,8 +63,8 @@
     }
   }
 
-  static void fixNamedConstructorTypeArgs(
-      DartFixRegistrar registrar, DartFixListener listener) {
+  static void fixNamedConstructorTypeArgs(DartFixRegistrar registrar,
+      DartFixListener listener, EditDartfixParams params) {
     registrar.registerErrorTask(
         StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR,
         new FixErrorTask(listener));
diff --git a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
index bc771f2..5a67460 100644
--- a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
@@ -2,12 +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:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/edit/fix/dartfix_listener.dart';
 import 'package:analysis_server/src/edit/fix/dartfix_registrar.dart';
 import 'package:analysis_server/src/edit/fix/fix_code_task.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_listener.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/overlay_file_system.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/task/options.dart';
@@ -26,17 +29,25 @@
 
   final DartFixListener listener;
 
-  final NullabilityMigration migration;
+  final String outputDir;
+
+  InstrumentationListener instrumentationListener;
+
+  NullabilityMigration migration;
 
   /// If this flag has a value of `false`, then something happened to prevent
   /// at least one package from being marked as non-nullable.
   /// If this occurs, then don't update any code.
   bool _packageIsNNBD = true;
 
-  NonNullableFix(this.listener)
-      : migration = new NullabilityMigration(
-            new NullabilityMigrationAdapter(listener),
-            permissive: _usePermissiveMode);
+  NonNullableFix(this.listener, this.outputDir) {
+    instrumentationListener =
+        outputDir == null ? null : InstrumentationListener();
+    migration = new NullabilityMigration(
+        new NullabilityMigrationAdapter(listener),
+        permissive: _usePermissiveMode,
+        instrumentation: instrumentationListener);
+  }
 
   @override
   int get numPhases => 2;
@@ -44,6 +55,14 @@
   @override
   Future<void> finish() async {
     migration.finish();
+    if (outputDir != null) {
+      OverlayResourceProvider provider = listener.server.resourceProvider;
+      Folder outputFolder = provider.getFolder(outputDir);
+      if (!outputFolder.exists) {
+        outputFolder.create();
+      }
+      _generateOutput(outputFolder);
+    }
   }
 
   /// If the package contains an analysis_options.yaml file, then update the
@@ -176,8 +195,21 @@
     _packageIsNNBD = false;
   }
 
-  static void task(DartFixRegistrar registrar, DartFixListener listener) {
-    registrar.registerCodeTask(new NonNullableFix(listener));
+  /// Generate output into the given [folder].
+  void _generateOutput(Folder folder) {
+    File main = folder.getChildAssumingFile('main.html');
+    main.writeAsStringSync('''
+<html>
+<body>
+Generated output at ${DateTime.now()}.
+</body>
+</html>
+''');
+  }
+
+  static void task(DartFixRegistrar registrar, DartFixListener listener,
+      EditDartfixParams params) {
+    registrar.registerCodeTask(new NonNullableFix(listener, params.outputDir));
   }
 }
 
diff --git a/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart b/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart
index 0d6bcef..4c784d7 100644
--- a/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/plugin/edit/assist/assist_core.dart';
+import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/edit/fix/dartfix_listener.dart';
 import 'package:analysis_server/src/edit/fix/dartfix_registrar.dart';
 import 'package:analysis_server/src/edit/fix/fix_code_task.dart';
@@ -91,7 +92,8 @@
   @override
   Future<void> processUnit(int phase, ResolvedUnitResult result) async {}
 
-  static void task(DartFixRegistrar registrar, DartFixListener listener) {
+  static void task(DartFixRegistrar registrar, DartFixListener listener,
+      EditDartfixParams params) {
     var task = new PreferMixinFix(listener);
     registrar.registerLintTask(Registry.ruleRegistry['prefer_mixin'], task);
     registrar.registerCodeTask(task);
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_information.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_information.dart
new file mode 100644
index 0000000..1e60891
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_information.dart
@@ -0,0 +1,84 @@
+// 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/element/element.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:nnbd_migration/instrumentation.dart';
+import 'package:nnbd_migration/nnbd_migration.dart';
+
+/// The instrumentation information gathered from the migration engine.
+class InstrumentationInformation {
+  /// The node used for type sources that are always `null`.
+  NullabilityNodeInfo always;
+
+  /// A map from elements outside of the code being migrated, to the nullability
+  /// nodes associated with the type of the element.
+  final Map<Element, DecoratedTypeInfo> externalDecoratedType = {};
+
+  /// A map from the graph edges between nullability nodes, to information about
+  /// the edge that was created and why it was created.
+  final Map<EdgeInfo, EdgeOriginInfo> edgeOrigin = {};
+
+  /// The node used for type sources that are never `null`.
+  NullabilityNodeInfo never;
+
+  /// A list of the steps in the propagation of nullability information through
+  /// the nullability graph, to report details of the step that was performed
+  /// and why it was performed.
+  final List<PropagationInfo> propagationSteps = [];
+
+  /// The instrumentation information that is specific to a single source.
+  final Map<Source, SourceInformation> sourceInformation = {};
+
+  /// Initialize a newly created holder of instrumentation information.
+  InstrumentationInformation();
+}
+
+/// The instrumentation information gathered from the migration engine that is
+/// specific to a single source.
+class SourceInformation {
+  /// A map from the type annotations found in the source code, to the
+  /// nullability nodes that are associated with that type.
+  final Map<TypeAnnotation, NullabilityNodeInfo> explicitTypeNullability = {};
+
+  /// A map from the fixes that were decided on to the reasons for the fix.
+  final Map<SingleNullabilityFix, List<FixReasonInfo>> fixes = {};
+
+  /// A map from AST nodes that have an implicit return type to the nullability
+  /// node associated with the implicit return type of the AST node. The node
+  /// can be an
+  /// - executable declaration,
+  /// - function-typed formal parameter declaration,
+  /// - function type alias declaration,
+  /// - generic function type, or
+  /// - function expression.
+  final Map<AstNode, DecoratedTypeInfo> implicitReturnType = {};
+
+  /// A map from AST nodes that have an implicit type to the nullability node
+  /// associated with the implicit type of the AST node. The node can be a
+  /// - formal parameter,
+  /// - declared identifier, or
+  /// - variable in a variable declaration list.
+  final Map<AstNode, DecoratedTypeInfo> implicitType = {};
+
+  /// Called whenever the migration engine encounters an AST node with implicit
+  /// type arguments, to report the nullability nodes associated with the
+  /// implicit type arguments of the AST node.
+  ///
+  /// A map from AST nodes that have implicit type arguments to the nullability
+  /// nodes associated with the implicit type arguments of the AST node. The
+  /// node can be a
+  /// - constructor redirection,
+  /// - function expression invocation,
+  /// - method invocation,
+  /// - instance creation expression,
+  /// - list/map/set literal, or
+  /// - type annotation.
+  final Map<AstNode, List<DecoratedTypeInfo>> implicitTypeArguments = {};
+
+  /// Initialize a newly created holder of instrumentation information that is
+  /// specific to a single source.
+  SourceInformation();
+}
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_listener.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_listener.dart
new file mode 100644
index 0000000..bb3f1d0
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_listener.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_information.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:nnbd_migration/instrumentation.dart';
+import 'package:nnbd_migration/nnbd_migration.dart';
+
+/// A listener used to gather instrumentation information from the migration
+/// engine.
+class InstrumentationListener implements NullabilityMigrationInstrumentation {
+  /// The instrumentation information being gathered.
+  InstrumentationInformation data = InstrumentationInformation();
+
+  /// Initialize a newly created listener.
+  InstrumentationListener();
+
+  @override
+  void explicitTypeNullability(
+      Source source, TypeAnnotation typeAnnotation, NullabilityNodeInfo node) {
+    _sourceInfo(source).explicitTypeNullability[typeAnnotation] = node;
+  }
+
+  @override
+  void externalDecoratedType(Element element, DecoratedTypeInfo decoratedType) {
+    data.externalDecoratedType[element] = decoratedType;
+  }
+
+  @override
+  void fix(SingleNullabilityFix fix, Iterable<FixReasonInfo> reasons) {
+    _sourceInfo(fix.source).fixes[fix] = reasons.toList();
+  }
+
+  @override
+  void graphEdge(EdgeInfo edge, EdgeOriginInfo originInfo) {
+    data.edgeOrigin[edge] = originInfo;
+  }
+
+  @override
+  void immutableNodes(NullabilityNodeInfo never, NullabilityNodeInfo always) {
+    data.never = never;
+    data.always = always;
+  }
+
+  @override
+  void implicitReturnType(
+      Source source, AstNode node, DecoratedTypeInfo decoratedReturnType) {
+    _sourceInfo(source).implicitReturnType[node] = decoratedReturnType;
+  }
+
+  @override
+  void implicitType(
+      Source source, AstNode node, DecoratedTypeInfo decoratedType) {
+    _sourceInfo(source).implicitType[node] = decoratedType;
+  }
+
+  @override
+  void implicitTypeArguments(
+      Source source, AstNode node, Iterable<DecoratedTypeInfo> types) {
+    _sourceInfo(source).implicitTypeArguments[node] = types.toList();
+  }
+
+  @override
+  void propagationStep(PropagationInfo info) {
+    data.propagationSteps.add(info);
+  }
+
+  /// Return the source information associated with the given [source], creating
+  /// it if there has been no previous information for that source.
+  SourceInformation _sourceInfo(Source source) =>
+      data.sourceInformation.putIfAbsent(source, () => SourceInformation());
+}
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
new file mode 100644
index 0000000..0fec5d3
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
@@ -0,0 +1,98 @@
+import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
+import 'package:mustache/mustache.dart' as mustache;
+
+/// Instrumentation display output for a library that was migrated to use non-nullable types.
+class InstrumentationRenderer {
+  /// Display information for a library.
+  final LibraryInfo info;
+
+  /// Creates an output object for the given library info.
+  InstrumentationRenderer(this.info);
+
+  /// Builds an HTML view of the instrumentation information in [info].
+  String render() {
+    int previousIndex = 0;
+    Map<String, dynamic> mustacheContext = {'units': <Map<String, dynamic>>[]};
+    for (var compilationUnit in info.units) {
+      StringBuffer buffer = StringBuffer();
+      for (var region in compilationUnit.regions) {
+        if (region.offset > previousIndex) {
+          // Display a region of unmodified content.
+          buffer.write(
+              compilationUnit.content.substring(previousIndex, region.offset));
+          previousIndex = region.offset + region.length;
+        }
+        buffer.write(_regionWithTooltip(region, compilationUnit.content));
+      }
+      if (previousIndex < compilationUnit.content.length) {
+        // Last region of unmodified content.
+        buffer.write(compilationUnit.content.substring(previousIndex));
+      }
+      mustacheContext['units']
+          .add({'path': compilationUnit.path, 'content': buffer.toString()});
+    }
+    return _template.renderString(mustacheContext);
+  }
+
+  String _regionWithTooltip(RegionInfo region, String content) {
+    String regionContent =
+        content.substring(region.offset, region.offset + region.length);
+    return '<span class="region">$regionContent'
+        '<span class="tooltip">${region.explanation}</span></span>';
+  }
+}
+
+/// A mustache template for one library's instrumentation output.
+mustache.Template _template = mustache.Template(r'''
+<html>
+  <head>
+    <title>Non-nullable fix instrumentation report</title>
+    <style>
+h2 {
+  font-size: 1em;
+  font-weight: bold;
+}
+
+div.content {
+  font-family: monospace;
+  whitespace: pre;
+}
+
+.region {
+  /* Green means this region was added. */
+  color: green;
+  display: inline-block;
+  position: relative;
+}
+
+.region .tooltip {
+  background-color: #EEE;
+  border: solid 2px #999;
+  color: #333;
+  left: 50%;
+  margin-left: -50px;
+  padding: 1px;
+  position: absolute;
+  top: 120%;
+  visibility: hidden;
+  width: 100px;
+  z-index: 1;
+}
+
+.region:hover .tooltip {
+  visibility: visible;
+}
+    </style>
+  </head>
+  <body>
+    <h1>Non-nullable fix instrumentation report</h1>
+    <p><em>Well-written introduction to this report.</em></p>
+    {{# units }}
+      <h2>{{ path }}</h2>
+      <div class="content">
+        {{{ content }}}
+      </div> {{! content }}
+    {{/ units }}
+  </body>
+</html>
+''');
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
new file mode 100644
index 0000000..2f872624
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart
@@ -0,0 +1,45 @@
+// 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 migration information associated with a single library.
+class LibraryInfo {
+  /// The information about the units in the library. The information about the
+  /// defining compilation unit is always first.
+  final List<UnitInfo> units;
+
+  /// Initialize a newly created library.
+  LibraryInfo(this.units);
+}
+
+/// A description of an explanation associated with a region of code that was
+/// modified.
+class RegionInfo {
+  /// The offset to the beginning of the region.
+  final int offset;
+
+  /// The length of the region.
+  final int length;
+
+  /// The explanation to be displayed for the region.
+  final String explanation;
+
+  /// Initialize a newly created region.
+  RegionInfo(this.offset, this.length, this.explanation);
+}
+
+/// The migration information associated with a single compilation unit.
+class UnitInfo {
+  /// The absolute and normalized path of the unit.
+  final String path;
+
+  /// The content of unit.
+  final String content;
+
+  /// The information about the regions that have an explanation associated with
+  /// them.
+  final List<RegionInfo> regions;
+
+  /// Initialize a newly created unit.
+  UnitInfo(this.path, this.content, this.regions);
+}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
index 25b0e2d..698e088 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
@@ -77,11 +77,6 @@
         var analysisDriver = server.getAnalysisDriver(data.file);
         var session = analysisDriver.currentSession;
 
-        var fileElement = await session.getUnitElement(data.file);
-        var libraryPath = fileElement.element.librarySource.fullName;
-
-        var resolvedLibrary = await session.getResolvedLibrary(libraryPath);
-
         if (token.isCancellationRequested) {
           return cancelled();
         }
@@ -115,14 +110,8 @@
 
         var newInsertText = item.insertText ?? item.label;
         final builder = DartChangeBuilder(session);
-        await builder.addFileEdit(libraryPath, (builder) {
-          final result = builder.importLibraryElement(
-            targetLibrary: resolvedLibrary,
-            targetPath: libraryPath,
-            targetOffset: data.offset,
-            requestedLibrary: requestedLibraryElement,
-            requestedElement: requestedElement,
-          );
+        await builder.addFileEdit(data.file, (builder) {
+          final result = builder.importLibraryElement(library.uri);
           if (result.prefix != null) {
             newInsertText = '${result.prefix}.$newInsertText';
           }
diff --git a/pkg/analysis_server/lib/src/search/type_hierarchy.dart b/pkg/analysis_server/lib/src/search/type_hierarchy.dart
index e4bcfe5..13e8262 100644
--- a/pkg/analysis_server/lib/src/search/type_hierarchy.dart
+++ b/pkg/analysis_server/lib/src/search/type_hierarchy.dart
@@ -52,12 +52,9 @@
    * Returns the computed type hierarchy, maybe `null`.
    */
   Future<List<TypeHierarchyItem>> compute() async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     if (_pivotClass != null) {
-      InterfaceType type = _pivotClass.type;
-      _createSuperItem(type);
-      await _createSubclasses(_items[0], 0, type);
+      _createSuperItem(_pivotClass, null);
+      await _createSubclasses(_items[0], 0, _pivotClass);
       return _items;
     }
     return null;
@@ -68,19 +65,15 @@
    */
   List<TypeHierarchyItem> computeSuper() {
     if (_pivotClass != null) {
-      InterfaceType type = _pivotClass.type;
-      _createSuperItem(type);
+      _createSuperItem(_pivotClass, null);
       return _items;
     }
     return null;
   }
 
   Future _createSubclasses(
-      TypeHierarchyItem item, int itemId, InterfaceType type) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
-    Set<ClassElement> subElements =
-        await getDirectSubClasses(_searchEngine, type.element);
+      TypeHierarchyItem item, int itemId, ClassElement classElement) async {
+    var subElements = await getDirectSubClasses(_searchEngine, classElement);
     List<int> subItemIds = <int>[];
     for (ClassElement subElement in subElements) {
       // check for recursion
@@ -110,14 +103,14 @@
     for (int subItemId in subItemIds) {
       TypeHierarchyItem subItem = _items[subItemId];
       ClassElement subItemElement = _itemClassElements[subItemId];
-      InterfaceType subType = subItemElement.type;
-      await _createSubclasses(subItem, subItemId, subType);
+      await _createSubclasses(subItem, subItemId, subItemElement);
     }
   }
 
-  int _createSuperItem(InterfaceType type) {
+  int _createSuperItem(
+      ClassElement classElement, List<DartType> typeArguments) {
     // check for recursion
-    TypeHierarchyItem item = _elementItemMap[type.element];
+    TypeHierarchyItem item = _elementItemMap[classElement];
     if (item != null) {
       return _items.indexOf(item);
     }
@@ -125,10 +118,10 @@
     int itemId;
     {
       String displayName = null;
-      if (type.typeArguments.isNotEmpty) {
-        displayName = type.toString();
+      if (typeArguments != null && typeArguments.isNotEmpty) {
+        displayName =
+            classElement.displayName + '<' + typeArguments.join(', ') + '>';
       }
-      ClassElement classElement = type.element;
       ExecutableElement memberElement = _findMemberElement(classElement);
       item = new TypeHierarchyItem(convertElement(classElement),
           displayName: displayName,
@@ -141,19 +134,22 @@
     }
     // superclass
     {
-      InterfaceType superType = type.superclass;
+      InterfaceType superType = classElement.supertype;
       if (superType != null) {
-        item.superclass = _createSuperItem(superType);
+        item.superclass = _createSuperItem(
+          superType.element,
+          superType.typeArguments,
+        );
       }
     }
     // mixins
-    type.mixins.forEach((InterfaceType type) {
-      int id = _createSuperItem(type);
+    classElement.mixins.forEach((InterfaceType type) {
+      int id = _createSuperItem(type.element, type.typeArguments);
       item.mixins.add(id);
     });
     // interfaces
-    type.interfaces.forEach((InterfaceType type) {
-      int id = _createSuperItem(type);
+    classElement.interfaces.forEach((InterfaceType type) {
+      int id = _createSuperItem(type.element, type.typeArguments);
       item.interfaces.add(id);
     });
     // done
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index f6febdc..15e715c 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -6,8 +6,6 @@
 import 'dart:ffi' as ffi;
 import 'dart:io';
 import 'dart:math';
-import 'package:analysis_server/src/utilities/request_statistics.dart';
-import 'package:path/path.dart' as path;
 
 import 'package:analysis_server/protocol/protocol_constants.dart'
     show PROTOCOL_VERSION;
@@ -25,11 +23,11 @@
 import 'package:analysis_server/src/services/completion/dart/uri_contributor.dart'
     show UriContributor;
 import 'package:analysis_server/src/socket_server.dart';
+import 'package:analysis_server/src/utilities/request_statistics.dart';
 import 'package:analysis_server/starter.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/instrumentation/file_instrumentation.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
@@ -37,6 +35,7 @@
 import 'package:args/args.dart';
 import 'package:front_end/src/fasta/compiler_context.dart';
 import 'package:linter/src/rules.dart' as linter;
+import 'package:path/path.dart' as path;
 import 'package:telemetry/crash_reporting.dart';
 import 'package:telemetry/telemetry.dart' as telemetry;
 
@@ -300,11 +299,6 @@
   static const String COMPLETION_MODEL_FOLDER = "completion-model";
 
   /**
-   * The name of the flag to use summary2.
-   */
-  static const String USE_SUMMARY2 = "use-summary2";
-
-  /**
    * A directory to analyze in order to train an analysis server snapshot.
    */
   static const String TRAIN_USING = "train-using";
@@ -370,8 +364,6 @@
           'lexeme');
     }
 
-    AnalysisDriver.useSummary2 = results[USE_SUMMARY2];
-
     bool disableAnalyticsForSession = results[SUPPRESS_ANALYTICS_FLAG];
     if (results.wasParsed(TRAIN_USING)) {
       disableAnalyticsForSession = true;
@@ -592,6 +584,36 @@
     }
   }
 
+  /// This will be invoked after createAnalysisServer has been called on the
+  /// socket server. At that point, we'll be able to send a server.error
+  /// notification in case model startup fails.
+  void startCompletionRanking(
+      SocketServer socketServer,
+      LspSocketServer lspSocketServer,
+      AnalysisServerOptions analysisServerOptions) {
+    if (analysisServerOptions.completionModelFolder == null ||
+        ffi.sizeOf<ffi.IntPtr>() == 4) {
+      return;
+    }
+
+    // Start completion model isolate if this is a 64 bit system and
+    // analysis server was configured to load a language model on disk.
+    CompletionRanking.instance =
+        CompletionRanking(analysisServerOptions.completionModelFolder);
+    CompletionRanking.instance.start().catchError((error) {
+      // Disable smart ranking if model startup fails.
+      analysisServerOptions.completionModelFolder = null;
+      CompletionRanking.instance = null;
+      if (socketServer != null) {
+        socketServer.analysisServer.sendServerErrorNotification(
+            'Failed to start ranking model isolate', error, error.stackTrace);
+      } else {
+        lspSocketServer.analysisServer.sendServerErrorNotification(
+            'Failed to start ranking model isolate', error, error.stackTrace);
+      }
+    });
+  }
+
   void startLspServer(
     ArgResults args,
     AnalysisServerOptions analysisServerOptions,
@@ -634,36 +656,6 @@
     });
   }
 
-  /// This will be invoked after createAnalysisServer has been called on the
-  /// socket server. At that point, we'll be able to send a server.error
-  /// notification in case model startup fails.
-  void startCompletionRanking(
-      SocketServer socketServer,
-      LspSocketServer lspSocketServer,
-      AnalysisServerOptions analysisServerOptions) {
-    if (analysisServerOptions.completionModelFolder == null ||
-        ffi.sizeOf<ffi.IntPtr>() == 4) {
-      return;
-    }
-
-    // Start completion model isolate if this is a 64 bit system and
-    // analysis server was configured to load a language model on disk.
-    CompletionRanking.instance =
-        CompletionRanking(analysisServerOptions.completionModelFolder);
-    CompletionRanking.instance.start().catchError((error) {
-      // Disable smart ranking if model startup fails.
-      analysisServerOptions.completionModelFolder = null;
-      CompletionRanking.instance = null;
-      if (socketServer != null) {
-        socketServer.analysisServer.sendServerErrorNotification(
-            'Failed to start ranking model isolate', error, error.stackTrace);
-      } else {
-        lspSocketServer.analysisServer.sendServerErrorNotification(
-            'Failed to start ranking model isolate', error, error.stackTrace);
-      }
-    });
-  }
-
   /**
    * Execute the given [callback] within a zone that will capture any unhandled
    * exceptions and both report them to the client and send them to the given
@@ -792,8 +784,6 @@
         help: "Whether or not to turn on ML ranking for code completion");
     parser.addOption(COMPLETION_MODEL_FOLDER,
         help: "[path] path to the location of a code completion model");
-    parser.addFlag(USE_SUMMARY2,
-        defaultsTo: false, help: "Whether to use summary2");
     parser.addOption(TRAIN_USING,
         help: "Pass in a directory to analyze for purposes of training an "
             "analysis server snapshot.");
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 4d77c9c..1a90a96 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
@@ -41,7 +41,7 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
-import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
index 8076baf..62a2c8b 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
@@ -76,6 +76,11 @@
   }
 
   @override
+  void declaredExtension(ExtensionDeclaration declaration) {
+    // ignored
+  }
+
+  @override
   void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
     // ignored
   }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
index 3e3cf86..4332192 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
@@ -11,8 +11,11 @@
     show DartCompletionRequestImpl;
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
 import 'package:analysis_server/src/services/completion/dart/utilities.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.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_plugin/protocol/protocol_common.dart' as protocol
     show Element, ElementKind;
 import 'package:analyzer_plugin/src/utilities/completion/optype.dart';
@@ -74,6 +77,9 @@
   void declaredClassTypeAlias(ClassTypeAlias declaration) {}
 
   @override
+  void declaredExtension(ExtensionDeclaration declaration) {}
+
+  @override
   void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {}
 
   @override
@@ -113,7 +119,7 @@
 
     ClassElement classElement = classDecl.declaredElement;
     int relevance = optype.returnValueSuggestionsFilter(
-        classElement?.type, DART_RELEVANCE_DEFAULT);
+        _instantiateClassElement(classElement), DART_RELEVANCE_DEFAULT);
     if (constructorDecl != null) {
       // Build a suggestion for explicitly declared constructor
       ConstructorElement element = constructorDecl.declaredElement;
@@ -157,4 +163,24 @@
       suggestions.add(suggestion);
     }
   }
+
+  InterfaceType _instantiateClassElement(ClassElement element) {
+    var typeParameters = element.typeParameters;
+    var typeArguments = const <DartType>[];
+    if (typeParameters.isNotEmpty) {
+      var typeProvider = request.libraryElement.context.typeProvider;
+      typeArguments = typeParameters.map((t) {
+        return typeProvider.dynamicType;
+      }).toList();
+    }
+
+    var nullabilitySuffix = request.featureSet.isEnabled(Feature.non_nullable)
+        ? NullabilitySuffix.none
+        : NullabilitySuffix.star;
+
+    return element.instantiate(
+      typeArguments: typeArguments,
+      nullabilitySuffix: nullabilitySuffix,
+    );
+  }
 }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
index 942b514..0aeeb94 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
@@ -8,7 +8,9 @@
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart'
     show createSuggestion, ElementSuggestionBuilder;
+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/dart/element/visitor.dart';
 import 'package:analyzer_plugin/src/utilities/completion/optype.dart';
@@ -47,21 +49,21 @@
     if (optype.includeTypeNameSuggestions) {
       // if includeTypeNameSuggestions, then use the filter
       int relevance = optype.typeNameSuggestionsFilter(
-          element.type, DART_RELEVANCE_DEFAULT);
+          _instantiateClassElement(element), DART_RELEVANCE_DEFAULT);
       if (relevance != null) {
         addSuggestion(element, prefix: prefix, relevance: relevance);
       }
     }
     if (optype.includeConstructorSuggestions) {
       int relevance = optype.returnValueSuggestionsFilter(
-          element.type, DART_RELEVANCE_DEFAULT);
+          _instantiateClassElement(element), DART_RELEVANCE_DEFAULT);
       _addConstructorSuggestions(element, relevance);
     }
     if (optype.includeReturnValueSuggestions) {
       if (element.isEnum) {
         String enumName = element.displayName;
         int relevance = optype.returnValueSuggestionsFilter(
-            element.type, DART_RELEVANCE_DEFAULT);
+            _instantiateClassElement(element), DART_RELEVANCE_DEFAULT);
         for (var field in element.fields) {
           if (field.isEnumConstant) {
             addSuggestion(field,
@@ -85,6 +87,14 @@
   }
 
   @override
+  void visitExtensionElement(ExtensionElement element) {
+    if (optype.includeReturnValueSuggestions) {
+      addSuggestion(element, prefix: prefix, relevance: DART_RELEVANCE_DEFAULT);
+    }
+    element.visitChildren(this);
+  }
+
+  @override
   void visitFunctionElement(FunctionElement element) {
     // Do not suggest operators or local functions
     if (element.isOperator) {
@@ -179,6 +189,26 @@
       }
     }
   }
+
+  InterfaceType _instantiateClassElement(ClassElement element) {
+    var typeParameters = element.typeParameters;
+    var typeArguments = const <DartType>[];
+    if (typeParameters.isNotEmpty) {
+      var typeProvider = request.libraryElement.context.typeProvider;
+      typeArguments = typeParameters.map((t) {
+        return typeProvider.dynamicType;
+      }).toList();
+    }
+
+    var nullabilitySuffix = request.featureSet.isEnabled(Feature.non_nullable)
+        ? NullabilitySuffix.none
+        : NullabilitySuffix.star;
+
+    return element.instantiate(
+      typeArguments: typeArguments,
+      nullabilitySuffix: nullabilitySuffix,
+    );
+  }
 }
 
 /**
@@ -190,8 +220,6 @@
   @override
   Future<List<CompletionSuggestion>> computeSuggestions(
       DartCompletionRequest request) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     if (!request.includeIdentifiers) {
       return const <CompletionSuggestion>[];
     }
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 f5b9ff3..1e2b426 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
@@ -11,9 +11,11 @@
     show DartCompletionRequestImpl;
 import 'package:analysis_server/src/services/completion/dart/utilities.dart';
 import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/util/comment.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol
@@ -160,6 +162,18 @@
   }
 
   @override
+  void declaredExtension(ExtensionDeclaration declaration) {
+    if (optype.includeReturnValueSuggestions) {
+      _addLocalSuggestion_includeReturnValueSuggestions(
+          declaration.documentationComment,
+          declaration.name,
+          NO_RETURN_TYPE,
+          protocol.ElementKind.EXTENSION,
+          isDeprecated: isDeprecated(declaration));
+    }
+  }
+
+  @override
   void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
     if ((optype.includeReturnValueSuggestions &&
             (!optype.inStaticMethodBody || fieldDecl.isStatic)) ||
@@ -444,8 +458,8 @@
       bool isDeprecated = false,
       int relevance = DART_RELEVANCE_DEFAULT}) {
     ClassElement classElement = enumDeclaration.declaredElement;
-    relevance =
-        optype.returnValueSuggestionsFilter(classElement?.type, relevance);
+    relevance = optype.returnValueSuggestionsFilter(
+        _instantiateClassElement(classElement), relevance);
     if (relevance != null) {
       _addLocalSuggestion_enumConstant(constantDeclaration, enumDeclaration,
           isAbstract: isAbstract,
@@ -524,6 +538,26 @@
     addDefaultArgDetails(suggestion, null, requiredParameters, namedParameters);
   }
 
+  InterfaceType _instantiateClassElement(ClassElement element) {
+    var typeParameters = element.typeParameters;
+    var typeArguments = const <DartType>[];
+    if (typeParameters.isNotEmpty) {
+      var typeProvider = request.libraryElement.context.typeProvider;
+      typeArguments = typeParameters.map((t) {
+        return typeProvider.dynamicType;
+      }).toList();
+    }
+
+    var nullabilitySuffix = request.featureSet.isEnabled(Feature.non_nullable)
+        ? NullabilitySuffix.none
+        : NullabilitySuffix.star;
+
+    return element.instantiate(
+      typeArguments: typeArguments,
+      nullabilitySuffix: nullabilitySuffix,
+    );
+  }
+
   bool _isVoid(TypeAnnotation returnType) {
     if (returnType is TypeName) {
       Identifier id = returnType.name;
@@ -536,7 +570,7 @@
 
   DartType _staticTypeOfIdentifier(Identifier id) {
     if (id.staticElement is ClassElement) {
-      return (id.staticElement as ClassElement).type;
+      return _instantiateClassElement(id.staticElement as ClassElement);
     } else {
       return id.staticType;
     }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
index 069c71d..ae865b9 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
@@ -9,8 +9,11 @@
 import 'package:analysis_server/src/protocol_server.dart' as protocol
     hide CompletionSuggestion, CompletionSuggestionKind;
 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/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
+import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
@@ -40,7 +43,8 @@
 
     // Generate a collection of inherited members
     var classElem = classDecl.declaredElement;
-    var interface = inheritance.getInterface(classElem.type);
+    var classType = _thisType(request, classElem);
+    var interface = inheritance.getInterface(classType);
     var interfaceMap = interface.map;
     var namesToOverride =
         _namesToOverride(classElem.librarySource.uri, interface);
@@ -192,4 +196,25 @@
     }
     return namesToOverride;
   }
+
+  InterfaceType _thisType(
+    DartCompletionRequest request,
+    ClassElement thisElement,
+  ) {
+    var typeParameters = thisElement.typeParameters;
+    var typeArguments = const <DartType>[];
+    if (typeParameters.isNotEmpty) {
+      var nullabilitySuffix = request.featureSet.isEnabled(Feature.non_nullable)
+          ? NullabilitySuffix.none
+          : NullabilitySuffix.star;
+      typeArguments = typeParameters.map((t) {
+        return t.instantiate(nullabilitySuffix: nullabilitySuffix);
+      }).toList();
+    }
+
+    return thisElement.instantiate(
+      typeArguments: typeArguments,
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+  }
 }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
index ca30c558..6e3172e 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
@@ -147,6 +147,9 @@
   }
 
   @override
+  void declaredExtension(ExtensionDeclaration declaration) {}
+
+  @override
   void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
     if (varDecl.name.name == targetName) {
       // Type provided by the element in computeFull above
diff --git a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
index 770f7eb5..c93417d 100644
--- a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
@@ -544,17 +544,6 @@
     Expression expr = list.firstWhere((expr) {
       DartType type = expr.staticType;
       if (type == null) return false;
-      if (typeSystem.isSubtypeOf(type, builtInType)) return true;
-      Element element = type.element;
-      if (element is TypeDefiningElement) {
-        TypeDefiningElement typeDefElem = element;
-        type = typeDefElem.type;
-        if (type is ParameterizedType) {
-          ParameterizedType pType = type;
-          type = pType.instantiate(new List.filled(
-              pType.typeParameters.length, typeProvider.dynamicType));
-        }
-      }
       return typeSystem.isSubtypeOf(type, builtInType);
     }, orElse: () => null);
     if (expr is SimpleIdentifier && expr.parent is PropertyAccess) {
diff --git a/pkg/analysis_server/lib/src/services/correction/assist.dart b/pkg/analysis_server/lib/src/services/correction/assist.dart
index 3d37042..6c51810 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -31,6 +31,8 @@
  * An enumeration of possible assist kinds.
  */
 class DartAssistKind {
+  static const ADD_NOT_NULL_ASSERT = const AssistKind(
+      'dart.assist.addNotNullAssert', 30, "Add a not-null assertion");
   static const ADD_TYPE_ANNOTATION = const AssistKind(
       'dart.assist.addTypeAnnotation', 30, "Add type annotation");
   static const ASSIGN_TO_LOCAL_VARIABLE = const AssistKind(
@@ -156,9 +158,7 @@
   static const IMPORT_ADD_SHOW = const AssistKind(
       'dart.assist.addShowCombinator', 30, "Add explicit 'show' combinator");
   static const INLINE_INVOCATION =
-      const AssistKind('dart.assist.inline', 30, "Inline invocation of '{0}'",
-          // todo (pq): migrate to (conditional) fix
-          associatedErrorCodes: <String>['prefer_inlined_adds']);
+      const AssistKind('dart.assist.inline', 30, "Inline invocation of '{0}'");
   static const INTRODUCE_LOCAL_CAST_TYPE = const AssistKind(
       'dart.assist.introduceLocalCast',
       30,
@@ -176,12 +176,10 @@
   static const JOIN_VARIABLE_DECLARATION = const AssistKind(
       'dart.assist.joinVariableDeclaration', 30, "Join variable declaration");
   static const REMOVE_TYPE_ANNOTATION = const AssistKind(
-      'dart.assist.removeTypeAnnotation', 29, "Remove type annotation",
-      // todo (pq): migrate to (conditional) fix
-      associatedErrorCodes: <String>[
-        'avoid_return_types_on_setters',
-        'type_init_formals'
-      ]);
+      // todo (pq): unify w/ fix
+      'dart.assist.removeTypeAnnotation',
+      29,
+      "Remove type annotation");
   static const REPLACE_CONDITIONAL_WITH_IF_ELSE = const AssistKind(
       'dart.assist.convert.conditionalToIfElse',
       30,
@@ -193,11 +191,7 @@
   static const SORT_CHILD_PROPERTY_LAST = const AssistKind(
       'dart.assist.sort.child.properties.last',
       30,
-      "Move child property to end of arguments",
-      // todo (pq): migrate to (conditional) fix
-      associatedErrorCodes: <String>[
-        'sort_child_properties_last',
-      ]);
+      "Move child property to end of arguments");
   static const SPLIT_AND_CONDITION = const AssistKind(
       'dart.assist.splitIfConjunction', 30, "Split && condition");
   static const SPLIT_VARIABLE_DECLARATION = const AssistKind(
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 8d88015..8daaf7b 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 import 'dart:collection';
+import 'dart:math';
 
 import 'package:analysis_server/plugin/edit/assist/assist_core.dart';
 import 'package:analysis_server/plugin/edit/assist/assist_dart.dart';
@@ -20,6 +21,7 @@
 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';
@@ -60,6 +62,7 @@
     )) {
       await _addProposals_addTypeAnnotation();
     }
+    await _addProposal_addNotNullAssert();
     await _addProposal_assignToLocalVariable();
     await _addProposal_convertClassToMixin();
     await _addProposal_convertDocumentationIntoBlock();
@@ -125,7 +128,11 @@
     await _addProposal_flutterWrapWidget();
     await _addProposal_flutterWrapWidgets();
     await _addProposal_importAddShow();
-    await _addProposal_inlineAdd();
+    if (!_containsErrorCode(
+      {LintNames.prefer_inlined_adds},
+    )) {
+      await _addProposal_inlineAdd();
+    }
     await _addProposal_introduceLocalTestedType();
     await _addProposal_invertIf();
     await _addProposal_joinIfStatementInner();
@@ -136,7 +143,11 @@
     await _addProposal_reparentFlutterList();
     await _addProposal_replaceConditionalWithIfElse();
     await _addProposal_replaceIfElseWithConditional();
-    await _addProposal_sortChildPropertyLast();
+    if (!_containsErrorCode(
+      {LintNames.sort_child_properties_last},
+    )) {
+      await _addProposal_sortChildPropertyLast();
+    }
     await _addProposal_splitAndCondition();
     await _addProposal_splitVariableDeclaration();
     await _addProposal_surroundWith();
@@ -159,10 +170,16 @@
       }
     }
     if (experimentStatus.spread_collections) {
+      final preferSpreadsLintFound =
+          _containsErrorCode({LintNames.prefer_spread_collections});
+      final preferInlinedAddsLintFound =
+          _containsErrorCode({LintNames.prefer_inlined_adds});
       if (!_containsErrorCode(
         {LintNames.prefer_spread_collections},
       )) {
-        await _addProposal_convertAddAllToSpread();
+        await _addProposal_convertAddAllToSpread(
+            preferInlinedAdds: !preferInlinedAddsLintFound,
+            convertToSpreads: !preferSpreadsLintFound);
       }
     }
 
@@ -210,6 +227,60 @@
     assists.add(new Assist(kind, change));
   }
 
+  Future<void> _addProposal_addNotNullAssert() async {
+    final identifier = this.node;
+    if (identifier is SimpleIdentifier) {
+      if (identifier.parent is FormalParameter) {
+        final exp = identifier.parent.thisOrAncestorMatching(
+            (node) => node is FunctionExpression || node is MethodDeclaration);
+        var body;
+        if (exp is FunctionExpression) {
+          body = exp.body;
+        } else if (exp is MethodDeclaration) {
+          body = exp.body;
+        }
+        if (body is BlockFunctionBody) {
+          // Check for an obvious pre-existing assertion.
+          for (var statement in body.block.statements) {
+            if (statement is AssertStatement) {
+              final condition = statement.condition;
+              if (condition is BinaryExpression) {
+                final leftOperand = condition.leftOperand;
+                if (leftOperand is SimpleIdentifier) {
+                  if (leftOperand.staticElement == identifier.staticElement &&
+                      condition.operator.type == TokenType.BANG_EQ &&
+                      condition.rightOperand is NullLiteral) {
+                    return;
+                  }
+                }
+              }
+            }
+          }
+
+          final changeBuilder = _newDartChangeBuilder();
+          await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+            final id = identifier.name;
+            final prefix = utils.getNodePrefix(exp);
+            final indent = utils.getIndent(1);
+            // todo (pq): follow-ups:
+            // 1. if the end token is on the same line as the body
+            // we should add an `eol` before the assert as well.
+            // 2. also, consider asking the block for the list of statements and
+            // adding the statement to the beginning of the list, special casing
+            // when there are no statements (or when there's a single statement
+            // and the whole block is on the same line).
+            final int offset = min(utils.getLineNext(body.beginToken.offset),
+                body.endToken.offset);
+            builder.addSimpleInsertion(
+                offset, '$prefix${indent}assert($id != null);$eol');
+            _addAssistFromBuilder(
+                changeBuilder, DartAssistKind.ADD_NOT_NULL_ASSERT);
+          });
+        }
+      }
+    }
+  }
+
   Future<void> _addProposal_assignToLocalVariable() async {
     // prepare enclosing ExpressionStatement
     ExpressionStatement expressionStatement;
@@ -263,9 +334,13 @@
     }
   }
 
-  Future<void> _addProposal_convertAddAllToSpread() async {
+  Future<void> _addProposal_convertAddAllToSpread(
+      {bool preferInlinedAdds = true, bool convertToSpreads = true}) async {
     final change = await createBuilder_convertAddAllToSpread();
     if (change != null) {
+      if (change.isLineInvocation && !preferInlinedAdds || !convertToSpreads) {
+        return;
+      }
       final kind = change.isLineInvocation
           ? DartAssistKind.INLINE_INVOCATION
           : DartAssistKind.CONVERT_TO_SPREAD;
@@ -497,7 +572,7 @@
     InstanceCreationExpression creation = node.thisOrAncestorOfType();
     if (creation == null ||
         node.offset > creation.argumentList.offset ||
-        creation.staticType.element != typeProvider.listType.element ||
+        creation.staticType.element != typeProvider.listElement ||
         creation.constructorName.name != null ||
         creation.argumentList.arguments.isNotEmpty) {
       _coverageMarker();
@@ -576,7 +651,7 @@
   Future<void> _addProposal_convertMapConstructorToMapLiteral() async {
     bool isMapClass(Element element) =>
         element is ClassElement &&
-        (element == typeProvider.mapType.element ||
+        (element == typeProvider.mapElement ||
             (element.name == 'LinkedHashMap' &&
                 element.library.name == 'dart.collection'));
     //
@@ -642,7 +717,7 @@
     InstanceCreationExpression creation = node.thisOrAncestorOfType();
     if (creation == null ||
         node.offset > creation.argumentList.offset ||
-        creation.staticType.element != typeProvider.setType.element) {
+        creation.staticType.element != typeProvider.setElement) {
       // TODO(brianwilkerson) Consider also accepting uses of LinkedHashSet.
       _coverageMarker();
       return;
@@ -699,7 +774,7 @@
       if (parent is VariableDeclaration) {
         AstNode parent2 = parent.parent;
         if (parent2 is VariableDeclarationList &&
-            parent2.type?.type?.element == typeProvider.setType.element) {
+            parent2.type?.type?.element == typeProvider.setElement) {
           return true;
         }
       }
@@ -944,9 +1019,8 @@
     // iterable should be List
     {
       DartType iterableType = iterable.staticType;
-      InterfaceType listType = typeProvider.listType;
       if (iterableType is! InterfaceType ||
-          iterableType.element != listType.element) {
+          iterableType.element != typeProvider.listElement) {
         _coverageMarker();
         return;
       }
@@ -1585,12 +1659,11 @@
     if (statefulWidgetClass == null || stateClass == null) {
       return;
     }
-    var stateType = stateClass.type.instantiate([widgetClassElement.type]);
 
     var changeBuilder = _newDartChangeBuilder();
     await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
       builder.addReplacement(range.node(superclass), (builder) {
-        builder.writeType(statefulWidgetClass.type);
+        builder.writeReference(statefulWidgetClass);
       });
 
       int replaceOffset = 0;
@@ -1661,6 +1734,16 @@
 
       // 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.writeClassDeclaration(stateName, superclass: stateType,
@@ -1867,7 +1950,7 @@
     var changeBuilder = _newDartChangeBuilder();
     await changeBuilder.addFileEdit(file, (builder) {
       builder.addReplacement(range.node(widgetExpr), (builder) {
-        builder.writeType(streamBuilderElement.type);
+        builder.writeReference(streamBuilderElement);
 
         builder.write('<');
         builder.addSimpleLinkedEdit('type', 'Object');
@@ -1963,7 +2046,7 @@
         if (parentClassElement == null) {
           builder.addSimpleLinkedEdit('WIDGET', 'widget');
         } else {
-          builder.writeType(parentClassElement.type);
+          builder.writeReference(parentClassElement);
         }
         builder.write('(');
         if (widgetSrc.contains(eol) || leadingLines.isNotEmpty) {
@@ -2038,7 +2121,7 @@
       var changeBuilder = _newDartChangeBuilder();
       await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
         builder.addReplacement(selectedRange, (DartEditBuilder builder) {
-          builder.writeType(parentClassElement.type);
+          builder.writeReference(parentClassElement);
           builder.write('(');
 
           String indentOld = utils.getLinePrefix(firstWidget.offset);
@@ -2048,7 +2131,7 @@
           builder.write(eol);
           builder.write(indentNew1);
           builder.write('children: <');
-          builder.writeType(widgetClassElement.type);
+          builder.writeReference(widgetClassElement);
           builder.write('>[');
           builder.write(eol);
 
@@ -2124,43 +2207,7 @@
   }
 
   Future<void> _addProposal_inlineAdd() async {
-    AstNode node = this.node;
-    if (node is! SimpleIdentifier || node.parent is! MethodInvocation) {
-      _coverageMarker();
-      return;
-    }
-    SimpleIdentifier name = node;
-    MethodInvocation invocation = node.parent;
-    if (name != invocation.methodName ||
-        name.name != 'add' ||
-        !invocation.isCascaded ||
-        invocation.argumentList.arguments.length != 1) {
-      _coverageMarker();
-      return;
-    }
-    CascadeExpression cascade = invocation.thisOrAncestorOfType();
-    NodeList<Expression> sections = cascade.cascadeSections;
-    Expression target = cascade.target;
-    if (target is! ListLiteral || sections[0] != invocation) {
-      // TODO(brianwilkerson) Consider extending this to handle set literals.
-      _coverageMarker();
-      return;
-    }
-    ListLiteral list = target;
-    Expression argument = invocation.argumentList.arguments[0];
-    String elementText = utils.getNodeText(argument);
-
-    DartChangeBuilder changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      if (list.elements.isNotEmpty) {
-        // ['a']..add(e);
-        builder.addSimpleInsertion(list.elements.last.end, ', $elementText');
-      } else {
-        // []..add(e);
-        builder.addSimpleInsertion(list.leftBracket.end, elementText);
-      }
-      builder.addDeletion(range.node(invocation));
-    });
+    final changeBuilder = await createBuilder_inlineAdd();
     _addAssistFromBuilder(changeBuilder, DartAssistKind.INLINE_INVOCATION,
         args: ['add']);
   }
@@ -2531,46 +2578,9 @@
   }
 
   Future<void> _addProposal_removeTypeAnnotation() async {
-    VariableDeclarationList declarationList =
-        node.thisOrAncestorOfType<VariableDeclarationList>();
-    if (declarationList == null) {
-      _coverageMarker();
-      return;
-    }
-    // we need a type
-    TypeAnnotation typeNode = declarationList.type;
-    if (typeNode == null) {
-      _coverageMarker();
-      return;
-    }
-    // ignore if an incomplete variable declaration
-    if (declarationList.variables.length == 1 &&
-        declarationList.variables[0].name.isSynthetic) {
-      _coverageMarker();
-      return;
-    }
-    // must be not after the name of the variable
-    VariableDeclaration firstVariable = declarationList.variables[0];
-    if (selectionOffset > firstVariable.name.end) {
-      _coverageMarker();
-      return;
-    }
-    // The variable must have an initializer, otherwise there is no other
-    // source for its type.
-    if (firstVariable.initializer == null) {
-      _coverageMarker();
-      return;
-    }
-    Token keyword = declarationList.keyword;
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      SourceRange typeRange = range.startStart(typeNode, firstVariable);
-      if (keyword != null && keyword.lexeme != 'var') {
-        builder.addSimpleReplacement(typeRange, '');
-      } else {
-        builder.addSimpleReplacement(typeRange, 'var ');
-      }
-    });
+    // todo (pq): unify w/ fix (and then add a guard to not assist on lints:
+    // avoid_return_types_on_setters, type_init_formals)
+    final changeBuilder = await createBuilder_removeTypeAnnotation();
     _addAssistFromBuilder(changeBuilder, DartAssistKind.REMOVE_TYPE_ANNOTATION);
   }
 
@@ -2791,42 +2801,7 @@
   }
 
   Future<void> _addProposal_sortChildPropertyLast() async {
-    NamedExpression childProp = flutter.findNamedExpression(node, 'child');
-    if (childProp == null) {
-      childProp = flutter.findNamedExpression(node, 'children');
-    }
-    if (childProp == null) {
-      return;
-    }
-
-    var parent = childProp.parent?.parent;
-    if (parent is! InstanceCreationExpression ||
-        !flutter.isWidgetCreation(parent)) {
-      return;
-    }
-
-    InstanceCreationExpression creationExpression = parent;
-    var args = creationExpression.argumentList;
-
-    var last = args.arguments.last;
-    if (last == childProp) {
-      // Already sorted.
-      return;
-    }
-
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      var start = childProp.beginToken.previous.end;
-      var end = childProp.endToken.next.end;
-      var childRange = range.startOffsetEndOffset(start, end);
-
-      var childText = utils.getRangeText(childRange);
-      builder.addSimpleReplacement(childRange, '');
-      builder.addSimpleInsertion(last.end + 1, childText);
-
-      changeBuilder.setSelection(new Position(file, last.end + 1));
-    });
-
+    final changeBuilder = await createBuilder_sortChildPropertyLast();
     _addAssistFromBuilder(
         changeBuilder, DartAssistKind.SORT_CHILD_PROPERTY_LAST);
   }
diff --git a/pkg/analysis_server/lib/src/services/correction/base_processor.dart b/pkg/analysis_server/lib/src/services/correction/base_processor.dart
index e054c8f..32e627e 100644
--- a/pkg/analysis_server/lib/src/services/correction/base_processor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/base_processor.dart
@@ -17,6 +17,7 @@
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_dart.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
@@ -412,7 +413,7 @@
     ConstructorElement element = creation.staticElement;
     if (element == null ||
         element.name != 'fromIterable' ||
-        element.enclosingElement != typeProvider.mapType.element) {
+        element.enclosingElement != typeProvider.mapElement) {
       _coverageMarker();
       return null;
     }
@@ -818,6 +819,132 @@
     return null;
   }
 
+  Future<ChangeBuilder> createBuilder_inlineAdd() async {
+    AstNode node = this.node;
+    if (node is! SimpleIdentifier || node.parent is! MethodInvocation) {
+      _coverageMarker();
+      return null;
+    }
+    SimpleIdentifier name = node;
+    MethodInvocation invocation = node.parent;
+    if (name != invocation.methodName ||
+        name.name != 'add' ||
+        !invocation.isCascaded ||
+        invocation.argumentList.arguments.length != 1) {
+      _coverageMarker();
+      return null;
+    }
+    CascadeExpression cascade = invocation.thisOrAncestorOfType();
+    NodeList<Expression> sections = cascade.cascadeSections;
+    Expression target = cascade.target;
+    if (target is! ListLiteral || sections[0] != invocation) {
+      // TODO(brianwilkerson) Consider extending this to handle set literals.
+      _coverageMarker();
+      return null;
+    }
+    ListLiteral list = target;
+    Expression argument = invocation.argumentList.arguments[0];
+    String elementText = utils.getNodeText(argument);
+
+    DartChangeBuilder changeBuilder = _newDartChangeBuilder();
+    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+      if (list.elements.isNotEmpty) {
+        // ['a']..add(e);
+        builder.addSimpleInsertion(list.elements.last.end, ', $elementText');
+      } else {
+        // []..add(e);
+        builder.addSimpleInsertion(list.leftBracket.end, elementText);
+      }
+      builder.addDeletion(range.node(invocation));
+    });
+    return changeBuilder;
+  }
+
+  Future<ChangeBuilder> createBuilder_sortChildPropertyLast() async {
+    NamedExpression childProp = flutter.findNamedExpression(node, 'child');
+    if (childProp == null) {
+      childProp = flutter.findNamedExpression(node, 'children');
+    }
+    if (childProp == null) {
+      return null;
+    }
+
+    var parent = childProp.parent?.parent;
+    if (parent is! InstanceCreationExpression ||
+        !flutter.isWidgetCreation(parent)) {
+      return null;
+    }
+
+    InstanceCreationExpression creationExpression = parent;
+    var args = creationExpression.argumentList;
+
+    var last = args.arguments.last;
+    if (last == childProp) {
+      // Already sorted.
+      return null;
+    }
+
+    var changeBuilder = _newDartChangeBuilder();
+    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+      var start = childProp.beginToken.previous.end;
+      var end = childProp.endToken.next.end;
+      var childRange = range.startOffsetEndOffset(start, end);
+
+      var childText = utils.getRangeText(childRange);
+      builder.addSimpleReplacement(childRange, '');
+      builder.addSimpleInsertion(last.end + 1, childText);
+
+      changeBuilder.setSelection(new Position(file, last.end + 1));
+    });
+
+    return changeBuilder;
+  }
+
+  /// todo (pq): unify with similar behavior in fix.
+  Future<ChangeBuilder> createBuilder_removeTypeAnnotation() async {
+    VariableDeclarationList declarationList =
+        node.thisOrAncestorOfType<VariableDeclarationList>();
+    if (declarationList == null) {
+      _coverageMarker();
+      return null;
+    }
+    // we need a type
+    TypeAnnotation typeNode = declarationList.type;
+    if (typeNode == null) {
+      _coverageMarker();
+      return null;
+    }
+    // ignore if an incomplete variable declaration
+    if (declarationList.variables.length == 1 &&
+        declarationList.variables[0].name.isSynthetic) {
+      _coverageMarker();
+      return null;
+    }
+    // must be not after the name of the variable
+    VariableDeclaration firstVariable = declarationList.variables[0];
+    if (selectionOffset > firstVariable.name.end) {
+      _coverageMarker();
+      return null;
+    }
+    // The variable must have an initializer, otherwise there is no other
+    // source for its type.
+    if (firstVariable.initializer == null) {
+      _coverageMarker();
+      return null;
+    }
+    Token keyword = declarationList.keyword;
+    var changeBuilder = _newDartChangeBuilder();
+    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+      SourceRange typeRange = range.startStart(typeNode, firstVariable);
+      if (keyword != null && keyword.lexeme != 'var') {
+        builder.addSimpleReplacement(typeRange, '');
+      } else {
+        builder.addSimpleReplacement(typeRange, 'var ');
+      }
+    });
+    return changeBuilder;
+  }
+
   @protected
   Future<ChangeBuilder> createBuilder_useCurlyBraces() async {
     Future<ChangeBuilder> doStatement(DoStatement node) async {
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index bac44cb..b2bc9a3 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -266,6 +266,8 @@
       "Move type arguments to after class name");
   static const MAKE_VARIABLE_NOT_FINAL = const FixKind(
       'MAKE_VARIABLE_NOT_FINAL', 50, "Make variable '{0}' not final");
+  static const QUALIFY_REFERENCE =
+      const FixKind('QUALIFY_REFERENCE', 50, "Use '{0}'");
   static const REMOVE_ANNOTATION =
       const FixKind('REMOVE_ANNOTATION', 50, "Remove the '{0}' annotation");
   static const REMOVE_AWAIT = const FixKind('REMOVE_AWAIT', 50, "Remove await");
@@ -310,15 +312,23 @@
       appliedTogetherMessage: "Remove all unnecessary casts in file");
   static const REMOVE_UNNECESSARY_CONST = const FixKind(
       'REMOVE_UNNECESSARY_CONST', 50, "Remove unnecessary const keyword");
+  static const REMOVE_UNNECESSARY_NEW = const FixKind(
+      'REMOVE_UNNECESSARY_NEW', 50, "Remove unnecessary new keyword");
   static const REMOVE_UNUSED_CATCH_CLAUSE = const FixKind(
       'REMOVE_UNUSED_CATCH_CLAUSE', 50, "Remove unused 'catch' clause");
   static const REMOVE_UNUSED_CATCH_STACK = const FixKind(
       'REMOVE_UNUSED_CATCH_STACK', 50, "Remove unused stack trace variable");
+  static const REMOVE_UNUSED_ELEMENT =
+      const FixKind('REMOVE_UNUSED_ELEMENT', 50, "Remove unused element");
+  static const REMOVE_UNUSED_FIELD =
+      const FixKind('REMOVE_UNUSED_FIELD', 50, "Remove unused field");
   static const REMOVE_UNUSED_IMPORT = const FixKind(
       'REMOVE_UNUSED_IMPORT', 50, "Remove unused import",
       appliedTogetherMessage: "Remove all unused imports in this file");
-  static const REMOVE_UNNECESSARY_NEW = const FixKind(
-      'REMOVE_UNNECESSARY_NEW', 50, "Remove unnecessary new keyword");
+  static const REMOVE_UNUSED_LABEL =
+      const FixKind('REMOVE_UNUSED_LABEL', 50, "Remove unused label");
+  static const REMOVE_UNUSED_LOCAL_VARIABLE = const FixKind(
+      'REMOVE_UNUSED_LOCAL_VARIABLE', 50, "Remove unused local variable");
   static const RENAME_TO_CAMEL_CASE =
       const FixKind('RENAME_TO_CAMEL_CASE', 50, "Rename to '{0}'");
   static const REPLACE_BOOLEAN_WITH_BOOL = const FixKind(
@@ -342,6 +352,8 @@
       const FixKind('REPLACE_WITH_BRACKETS', 50, "Replace with { }");
   static const REPLACE_WITH_CONDITIONAL_ASSIGNMENT = const FixKind(
       'REPLACE_WITH_CONDITIONAL_ASSIGNMENT', 50, "Replace with ??=");
+  static const REPLACE_WITH_EXTENSION_NAME =
+      const FixKind('REPLACE_WITH_EXTENSION_NAME', 50, "Replace with '{0}'");
   static const REPLACE_WITH_IDENTIFIER =
       const FixKind('REPLACE_WITH_IDENTIFIER', 50, "Replace with identifier");
   static const REPLACE_WITH_IS_EMPTY =
@@ -354,6 +366,10 @@
       "Replace the '.' with a '?.' in the invocation");
   static const REPLACE_WITH_TEAR_OFF = const FixKind(
       'REPLACE_WITH_TEAR_OFF', 50, "Replace function literal with tear-off");
+  static const SORT_CHILD_PROPERTY_LAST = const FixKind(
+      'SORT_CHILD_PROPERTY_LAST',
+      50,
+      "Move child property to end of arguments");
   static const UPDATE_SDK_CONSTRAINTS =
       const FixKind('UPDATE_SDK_CONSTRAINTS', 50, "Update the SDK constraints");
   static const USE_CONST = const FixKind('USE_CONST', 50, "Change to constant");
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 491d0e2..7dff396 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -18,10 +18,13 @@
 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:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/precedence.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/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/file_system.dart';
@@ -191,7 +194,13 @@
           workspace: context.workspace,
         );
 
-  DartType get coreTypeBool => _getCoreType('bool');
+  DartType get coreTypeBool => context.resolveResult.typeProvider.boolType;
+
+  FeatureSet get _featureSet {
+    return unit.featureSet;
+  }
+
+  bool get _isNonNullable => _featureSet.isEnabled(Feature.non_nullable);
 
   Future<List<Fix>> compute() async {
     node = new NodeLocator2(errorOffset).searchWithin(unit);
@@ -363,25 +372,21 @@
     if (errorCode == HintCode.UNUSED_CATCH_STACK) {
       await _addFix_removeUnusedCatchStack();
     }
-    // TODO(brianwilkerson) Add a fix to remove the declaration. Decide whether
-    //  this should be a single general fix, or multiple more specific fixes
-    //  such as [_addFix_removeMethodDeclaration].
-//    if (errorCode == HintCode.UNUSED_ELEMENT ||
-//        errorCode == HintCode.UNUSED_FIELD) {
-//      await _addFix_removeUnusedDeclaration();
-//    }
+    if (errorCode == HintCode.UNUSED_ELEMENT) {
+      await _addFix_removeUnusedElement();
+    }
+    if (errorCode == HintCode.UNUSED_FIELD) {
+      await _addFix_removeUnusedField();
+    }
     if (errorCode == HintCode.UNUSED_IMPORT) {
       await _addFix_removeUnusedImport();
     }
-    // TODO(brianwilkerson) Add a fix to remove the label.
-//    if (errorCode == HintCode.UNUSED_LABEL) {
-//      await _addFix_removeUnusedLabel();
-//    }
-    // TODO(brianwilkerson) Add a fix to remove the local variable, either with
-    //  or without the initialization code.
-//    if (errorCode == HintCode.UNUSED_LOCAL_VARIABLE) {
-//      await _addFix_removeUnusedLocalVariable();
-//    }
+    if (errorCode == HintCode.UNUSED_LABEL) {
+      await _addFix_removeUnusedLabel();
+    }
+    if (errorCode == HintCode.UNUSED_LOCAL_VARIABLE) {
+      await _addFix_removeUnusedLocalVariable();
+    }
     if (errorCode == HintCode.UNUSED_SHOWN_NAME) {
       await _addFix_removeNameFromCombinator();
     }
@@ -394,6 +399,9 @@
     if (errorCode == ParserErrorCode.VAR_AS_TYPE_NAME) {
       await _addFix_replaceVarWithDynamic();
     }
+    if (errorCode == ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE) {
+      await _addFix_addTypeAnnotation();
+    }
     if (errorCode == StaticWarningCode.ASSIGNMENT_TO_FINAL) {
       await _addFix_makeFieldNotFinal();
     }
@@ -563,6 +571,26 @@
     if (errorCode == StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH) {
       await _addFix_addMissingEnumCaseClauses();
     }
+    if (errorCode ==
+        CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER) {
+      await _addFix_replaceWithExtensionName();
+    }
+    if (errorCode ==
+        CompileTimeErrorCode
+            .UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE) {
+      await _addFix_qualifyReference();
+      // TODO(brianwilkerson) Consider adding fixes to create a field, getter,
+      //  method or setter. The existing _addFix methods would need to be
+      //  updated so that only the appropriate subset is generated.
+    }
+    if (errorCode ==
+        StaticTypeWarningCode
+            .UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER) {
+      await _addFix_qualifyReference();
+      // TODO(brianwilkerson) Consider adding fixes to create a field, getter,
+      //  method or setter. The existing _addFix methods would need to be
+      //  updated so that only the appropriate subset is generated.
+    }
     // lints
     if (errorCode is LintCode) {
       String name = errorCode.name;
@@ -643,6 +671,9 @@
           LintNames.prefer_if_elements_to_conditional_expressions) {
         await _addFix_convertConditionalToIfElement();
       }
+      if (name == LintNames.prefer_inlined_adds) {
+        await _addFix_convertToInlineAdd();
+      }
       if (name == LintNames.prefer_int_literals) {
         await _addFix_convertToIntLiteral();
       }
@@ -668,6 +699,9 @@
       if (name == LintNames.prefer_spread_collections) {
         await _addFix_convertAddAllToSpread();
       }
+      if (name == LintNames.sort_child_properties_last) {
+        await _addFix_sortChildPropertiesLast();
+      }
       if (name == LintNames.type_init_formals) {
         await _addFix_removeTypeAnnotation();
       }
@@ -1287,6 +1321,16 @@
     }
   }
 
+  Future<void> _addFix_convertAddAllToSpread() async {
+    final change = await createBuilder_convertAddAllToSpread();
+    if (change != null) {
+      final kind = change.isLineInvocation
+          ? DartFixKind.INLINE_INVOCATION
+          : DartFixKind.CONVERT_TO_SPREAD;
+      _addFixFromBuilder(change.builder, kind, args: change.args);
+    }
+  }
+
   Future<void> _addFix_convertConditionalToIfElement() async {
     final changeBuilder =
         await createBuilder_convertConditionalExpressionToIfElement();
@@ -1383,6 +1427,12 @@
     _addFixFromBuilder(changeBuilder, DartFixKind.CONVERT_INTO_EXPRESSION_BODY);
   }
 
+  Future<void> _addFix_convertToInlineAdd() async {
+    final changeBuilder = await createBuilder_inlineAdd();
+    _addFixFromBuilder(changeBuilder, DartFixKind.INLINE_INVOCATION,
+        args: ['add']);
+  }
+
   Future<void> _addFix_convertToIntLiteral() async {
     final changeBuilder = await createBuilder_convertToIntLiteral();
     _addFixFromBuilder(changeBuilder, DartFixKind.CONVERT_TO_INT_LITERAL);
@@ -1594,7 +1644,14 @@
           builder.write('const ');
           builder.write(className);
           builder.write('({');
-          builder.writeType(keyClass.type);
+          builder.writeType(
+            keyClass.instantiate(
+              typeArguments: const [],
+              nullabilitySuffix: _isNonNullable
+                  ? NullabilitySuffix.question
+                  : NullabilitySuffix.star,
+            ),
+          );
           builder.write(' key');
 
           List<String> childrenFields = [];
@@ -1877,16 +1934,6 @@
     }
   }
 
-  Future<void> _addFix_convertAddAllToSpread() async {
-    final change = await createBuilder_convertAddAllToSpread();
-    if (change != null) {
-      final kind = change.isLineInvocation
-          ? DartFixKind.INLINE_INVOCATION
-          : DartFixKind.CONVERT_TO_SPREAD;
-      _addFixFromBuilder(change.builder, kind, args: change.args);
-    }
-  }
-
   Future<void> _addFix_createField() async {
     if (node is! SimpleIdentifier) {
       return;
@@ -3020,6 +3067,38 @@
     _addFixFromBuilder(changeBuilder, DartFixKind.ADD_NE_NULL);
   }
 
+  Future<void> _addFix_qualifyReference() async {
+    if (node is! SimpleIdentifier) {
+      return;
+    }
+    SimpleIdentifier memberName = node;
+    AstNode parent = node.parent;
+    AstNode target = null;
+    if (parent is MethodInvocation && node == parent.methodName) {
+      target = parent.target;
+    } else if (parent is PropertyAccess && node == parent.propertyName) {
+      target = parent.target;
+    }
+    if (target != null) {
+      return;
+    }
+    Element enclosingElement = memberName.staticElement.enclosingElement;
+    if (enclosingElement.library != unitLibraryElement) {
+      // TODO(brianwilkerson) Support qualifying references to members defined
+      //  in other libraries. `DartEditBuilder` currently defines the method
+      //  `writeType`, which is close, but we also need to handle extensions,
+      //  which don't have a type.
+      return;
+    }
+    String containerName = enclosingElement.name;
+    var changeBuilder = _newDartChangeBuilder();
+    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addSimpleInsertion(node.offset, '$containerName.');
+    });
+    _addFixFromBuilder(changeBuilder, DartFixKind.QUALIFY_REFERENCE,
+        args: ['$containerName.${memberName.name}']);
+  }
+
   Future<void> _addFix_removeAnnotation() async {
     void addFix(Annotation node) async {
       if (node == null) {
@@ -3446,6 +3525,110 @@
     }
   }
 
+  Future<void> _addFix_removeUnusedField() async {
+    final declaration = node.parent;
+    if (declaration is! VariableDeclaration) {
+      return;
+    }
+    final element = (declaration as VariableDeclaration).declaredElement;
+    if (element is! FieldElement) {
+      return;
+    }
+
+    final sourceRanges = <SourceRange>[];
+    final references = _findAllReferences(unit, element);
+    for (var reference in references) {
+      // todo (pq): consider scoping this to parent or parent.parent.
+      final referenceNode = reference.thisOrAncestorMatching((node) =>
+          node is VariableDeclaration ||
+          node is ExpressionStatement ||
+          node is ConstructorFieldInitializer ||
+          node is FieldFormalParameter);
+      if (referenceNode == null) {
+        return;
+      }
+      var sourceRange;
+      if (referenceNode is VariableDeclaration) {
+        VariableDeclarationList parent = referenceNode.parent;
+        if (parent.variables.length == 1) {
+          sourceRange = utils.getLinesRange(range.node(parent.parent));
+        } else {
+          sourceRange = range.nodeInList(parent.variables, referenceNode);
+        }
+      } else if (referenceNode is ConstructorFieldInitializer) {
+        ConstructorDeclaration cons =
+            referenceNode.parent as ConstructorDeclaration;
+        // A() : _f = 0;
+        if (cons.initializers.length == 1) {
+          sourceRange = range.endEnd(cons.parameters, referenceNode);
+        } else {
+          sourceRange = range.nodeInList(cons.initializers, referenceNode);
+        }
+      } else if (referenceNode is FieldFormalParameter) {
+        FormalParameterList params =
+            referenceNode.parent as FormalParameterList;
+        if (params.parameters.length == 1) {
+          sourceRange =
+              range.endStart(params.leftParenthesis, params.rightParenthesis);
+        } else {
+          sourceRange = range.nodeInList(params.parameters, referenceNode);
+        }
+      } else {
+        sourceRange = utils.getLinesRange(range.node(referenceNode));
+      }
+      sourceRanges.add(sourceRange);
+    }
+
+    final changeBuilder = _newDartChangeBuilder();
+    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+      for (var sourceRange in sourceRanges) {
+        builder.addDeletion(sourceRange);
+      }
+    });
+    _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_UNUSED_FIELD);
+  }
+
+  Future<void> _addFix_removeUnusedElement() async {
+    final sourceRanges = <SourceRange>[];
+    final referencedNode = node.parent;
+    if (referencedNode is ClassDeclaration ||
+        referencedNode is EnumDeclaration ||
+        referencedNode is FunctionDeclaration ||
+        referencedNode is FunctionTypeAlias ||
+        referencedNode is MethodDeclaration ||
+        referencedNode is VariableDeclaration) {
+      final element = referencedNode is Declaration
+          ? referencedNode.declaredElement
+          : (referencedNode as NamedCompilationUnitMember).declaredElement;
+      final references = _findAllReferences(unit, element);
+      // todo (pq): consider filtering for references that are limited to within the class.
+      if (references.length == 1) {
+        var sourceRange;
+        if (referencedNode is VariableDeclaration) {
+          VariableDeclarationList parent = referencedNode.parent;
+          if (parent.variables.length == 1) {
+            sourceRange = utils.getLinesRange(range.node(parent.parent));
+          } else {
+            sourceRange = range.nodeInList(parent.variables, node);
+          }
+        } else {
+          sourceRange = utils.getLinesRange(range.node(referencedNode));
+        }
+        sourceRanges.add(sourceRange);
+      }
+    }
+
+    if (sourceRanges.isNotEmpty) {
+      final changeBuilder = _newDartChangeBuilder();
+      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+        for (var sourceRange in sourceRanges) {
+          builder.addDeletion(sourceRange);
+        }
+      });
+      _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_UNUSED_ELEMENT);
+    }
+  }
+
   Future<void> _addFix_removeUnusedImport() async {
     // prepare ImportDirective
     ImportDirective importDirective =
@@ -3461,6 +3644,66 @@
     _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_UNUSED_IMPORT);
   }
 
+  Future<void> _addFix_removeUnusedLabel() async {
+    final parent = node.parent;
+    if (parent is Label) {
+      var nextToken = parent.endToken.next;
+      final changeBuilder = _newDartChangeBuilder();
+      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+        builder.addDeletion(range.startStart(parent, nextToken));
+      });
+      _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_UNUSED_LABEL);
+    }
+  }
+
+  Future<void> _addFix_removeUnusedLocalVariable() async {
+    final declaration = node.parent;
+    if (!(declaration is VariableDeclaration && declaration.name == node)) {
+      return;
+    }
+    Element element = (declaration as VariableDeclaration).declaredElement;
+    if (element is! LocalElement) {
+      return;
+    }
+
+    final sourceRanges = <SourceRange>[];
+
+    final functionBody = declaration.thisOrAncestorOfType<FunctionBody>();
+    final references = findLocalElementReferences(functionBody, element);
+    for (var reference in references) {
+      final node = reference.thisOrAncestorMatching((node) =>
+          node is VariableDeclaration || node is AssignmentExpression);
+      var sourceRange;
+      if (node is VariableDeclaration) {
+        VariableDeclarationList parent = node.parent;
+        if (parent.variables.length == 1) {
+          sourceRange = utils.getLinesRange(range.node(parent.parent));
+        } else {
+          sourceRange = range.nodeInList(parent.variables, node);
+        }
+      } else if (node is AssignmentExpression) {
+        // todo (pq): consider node.parent is! ExpressionStatement to handle
+        // assignments in parens, etc.
+        if (node.parent is ArgumentList) {
+          sourceRange = range.startStart(node, node.operator.next);
+        } else {
+          sourceRange = utils.getLinesRange(range.node(node.parent));
+        }
+      } else {
+        return;
+      }
+      sourceRanges.add(sourceRange);
+    }
+
+    final changeBuilder = _newDartChangeBuilder();
+    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+      for (var sourceRange in sourceRanges) {
+        builder.addDeletion(sourceRange);
+      }
+    });
+    _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_UNUSED_LOCAL_VARIABLE);
+  }
+
   Future<void> _addFix_renameToCamelCase() async {
     if (node is! SimpleIdentifier) {
       return;
@@ -3634,6 +3877,30 @@
     }
   }
 
+  Future<void> _addFix_replaceWithExtensionName() async {
+    if (node is! SimpleIdentifier) {
+      return;
+    }
+    AstNode parent = node.parent;
+    AstNode target = null;
+    if (parent is MethodInvocation && node == parent.methodName) {
+      target = parent.target;
+    } else if (parent is PropertyAccess && node == parent.propertyName) {
+      target = parent.target;
+    }
+    if (target is! ExtensionOverride) {
+      return;
+    }
+    ExtensionOverride override = target;
+    var changeBuilder = _newDartChangeBuilder();
+    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addSimpleReplacement(
+          range.node(override), utils.getNodeText(override.extensionName));
+    });
+    _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_WITH_EXTENSION_NAME,
+        args: [override.extensionName.name]);
+  }
+
   Future<void> _addFix_replaceWithIdentifier() async {
     final FunctionTypedFormalParameter functionTyped =
         node.thisOrAncestorOfType<FunctionTypedFormalParameter>();
@@ -3789,6 +4056,11 @@
     }
   }
 
+  Future<void> _addFix_sortChildPropertiesLast() async {
+    final changeBuilder = await createBuilder_sortChildPropertyLast();
+    _addFixFromBuilder(changeBuilder, DartFixKind.SORT_CHILD_PROPERTY_LAST);
+  }
+
   Future<void> _addFix_undefinedClass_useSimilar() async {
     AstNode node = this.node;
     // Prepare the optional import prefix name.
@@ -4324,6 +4596,12 @@
     _addFixFromBuilder(changeBuilder, DartFixKind.CREATE_METHOD, args: [name]);
   }
 
+  List<SimpleIdentifier> _findAllReferences(AstNode root, Element element) {
+    var collector = _ElementReferenceCollector(element);
+    root.accept(collector);
+    return collector.references;
+  }
+
   /// Return the class, enum or mixin declaration for the given [element].
   Future<ClassOrMixinDeclaration> _getClassDeclaration(
       ClassElement element) async {
@@ -4350,23 +4628,6 @@
     return buffer.toString();
   }
 
-  /**
-   * Returns the [DartType] with given name from the `dart:core` library.
-   */
-  DartType _getCoreType(String name) {
-    List<LibraryElement> libraries = unitLibraryElement.importedLibraries;
-    for (LibraryElement library in libraries) {
-      if (library.isDartCore) {
-        ClassElement classElement = library.getType(name);
-        if (classElement != null) {
-          return classElement.type;
-        }
-        return null;
-      }
-    }
-    return null;
-  }
-
   /// Return the extension declaration for the given [element].
   Future<ExtensionDeclaration> _getExtensionDeclaration(
       ExtensionElement element) async {
@@ -4730,6 +4991,32 @@
   }
 }
 
+class _ElementReferenceCollector extends RecursiveAstVisitor<void> {
+  final Element element;
+  final List<SimpleIdentifier> references = [];
+
+  _ElementReferenceCollector(this.element);
+
+  @override
+  void visitSimpleIdentifier(SimpleIdentifier node) {
+    final staticElement = node.staticElement;
+    if (staticElement == element) {
+      references.add(node);
+    }
+    // Implicit Setter.
+    else if (staticElement is PropertyAccessorElement) {
+      if (staticElement.variable == element) {
+        references.add(node);
+      }
+      // Field Formals.
+    } else if (staticElement is FieldFormalParameterElement) {
+      if (staticElement.field == element) {
+        references.add(node);
+      }
+    }
+  }
+}
+
 /**
  * [ExecutableElement], its parameters, and operations on them.
  */
diff --git a/pkg/analysis_server/lib/src/services/flutter/class_description.dart b/pkg/analysis_server/lib/src/services/flutter/class_description.dart
index d8f2e4d..5ab9dca 100644
--- a/pkg/analysis_server/lib/src/services/flutter/class_description.dart
+++ b/pkg/analysis_server/lib/src/services/flutter/class_description.dart
@@ -44,21 +44,17 @@
     _map.clear();
   }
 
-  /// If the [type] is a class, and we know how to materialize it, return its
-  /// [ClassDescription]. Otherwise return `null`.
-  ClassDescription get(DartType type) {
-    if (type is InterfaceType) {
-      var element = type.element;
-      var description = _map[element];
-      if (description == null) {
-        description = _classDescription(element);
-        if (description != null) {
-          _map[element] = description;
-        }
+  /// If we know how to materialize the [element], return [ClassDescription].
+  /// Otherwise return `null`.
+  ClassDescription get(ClassElement element) {
+    var description = _map[element];
+    if (description == null) {
+      description = _classDescription(element);
+      if (description != null) {
+        _map[element] = description;
       }
-      return description;
     }
-    return null;
+    return description;
   }
 
   /// Return `true` if properties should be created for instances of [type].
diff --git a/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart b/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart
index 1a16579..85a0e5e 100644
--- a/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart
+++ b/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart
@@ -199,7 +199,7 @@
         (property) => property.name == 'child',
       );
     } else {
-      var containerDescription = classRegistry.get(_classContainer.type);
+      var containerDescription = classRegistry.get(_classContainer);
       containerProperty = PropertyDescription(
         resolvedUnit: resolvedUnit,
         classDescription: containerDescription,
@@ -364,15 +364,18 @@
         );
       }
     } else if (valueExpression == null) {
-      var classDescription = classRegistry.get(
-        parameter.type,
-      );
-      if (classDescription != null) {
-        _addProperties(
-          properties: propertyDescription.children,
-          parent: propertyDescription,
-          classDescription: classDescription,
+      var type = parameter.type;
+      if (type is InterfaceType) {
+        var classDescription = classRegistry.get(
+          type.element,
         );
+        if (classDescription != null) {
+          _addProperties(
+            properties: propertyDescription.children,
+            parent: propertyDescription,
+            classDescription: classDescription,
+          );
+        }
       }
     }
   }
diff --git a/pkg/analysis_server/lib/src/services/kythe/kythe_visitors.dart b/pkg/analysis_server/lib/src/services/kythe/kythe_visitors.dart
index e9346c0..df5ebac 100644
--- a/pkg/analysis_server/lib/src/services/kythe/kythe_visitors.dart
+++ b/pkg/analysis_server/lib/src/services/kythe/kythe_visitors.dart
@@ -4,11 +4,13 @@
 
 import 'dart:convert';
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/syntactic_entity.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/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/visitor.dart';
 import 'package:analyzer/file_system/file_system.dart';
@@ -97,8 +99,10 @@
   final String _contents;
 
   String _enclosingFilePath = '';
+  FeatureSet _enclosingUnitFeatureSet;
   Element _enclosingElement;
   ClassElement _enclosingClassElement;
+  InterfaceType _enclosingClassThisType;
   KytheVName _enclosingVName;
   KytheVName _enclosingFileVName;
   KytheVName _enclosingClassVName;
@@ -339,6 +343,7 @@
   @override
   visitCompilationUnit(CompilationUnit node) {
     _enclosingFilePath = _getPath(resourceProvider, node.declaredElement);
+    _enclosingUnitFeatureSet = node.featureSet;
     return _withEnclosingElement(node.declaredElement, () {
       addFact(_enclosingFileVName, schema.NODE_KIND_FACT,
           _encode(schema.FILE_KIND));
@@ -692,7 +697,7 @@
 
       // override edges
       var overriddenList = _inheritanceManager.getOverridden(
-        _enclosingClassElement.type,
+        _enclosingClassThisType,
         new Name(
           _enclosingClassElement.library.source.uri,
           node.declaredElement.name,
@@ -1080,6 +1085,17 @@
         _enclosingClassElement = element;
         _enclosingClassVName = _enclosingVName =
             _vNameFromElement(_enclosingClassElement, schema.RECORD_KIND);
+        _enclosingClassThisType = element.instantiate(
+          typeArguments: element.typeParameters.map((t) {
+            return t.instantiate(
+              nullabilitySuffix:
+                  _enclosingUnitFeatureSet.isEnabled(Feature.non_nullable)
+                      ? NullabilitySuffix.none
+                      : NullabilitySuffix.star,
+            );
+          }).toList(),
+          nullabilitySuffix: NullabilitySuffix.none,
+        );
       } else if (element is MethodElement ||
           element is FunctionElement ||
           element is ConstructorElement) {
diff --git a/pkg/analysis_server/lib/src/services/linter/lint_names.dart b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
index b935e7f..b3ee6f1 100644
--- a/pkg/analysis_server/lib/src/services/linter/lint_names.dart
+++ b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
@@ -40,6 +40,7 @@
   static const String prefer_final_locals = 'prefer_final_locals';
   static const String prefer_for_elements_to_map_fromIterable =
       'prefer_for_elements_to_map_fromIterable';
+  static const String prefer_inlined_adds = 'prefer_inlined_adds';
   static const String prefer_int_literals = 'prefer_int_literals';
   static const String prefer_if_elements_to_conditional_expressions =
       'prefer_if_elements_to_conditional_expressions';
@@ -48,8 +49,9 @@
   static const String prefer_null_aware_operators =
       'prefer_null_aware_operators';
   static const String prefer_single_quotes = 'prefer_single_quotes';
-  static const String slash_for_doc_comments = 'slash_for_doc_comments';
   static const String prefer_spread_collections = 'prefer_spread_collections';
+  static const String slash_for_doc_comments = 'slash_for_doc_comments';
+  static const String sort_child_properties_last = 'sort_child_properties_last';
   static const String type_annotate_public_apis = 'type_annotate_public_apis';
   static const String type_init_formals = 'type_init_formals';
   static const String unawaited_futures = 'unawaited_futures';
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
index a495f56..74d6eb3 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
@@ -800,29 +800,28 @@
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
     TypeProvider typeProvider = await resolveResult.session.typeProvider;
-    InterfaceType futureType = typeProvider.futureType;
     if (_selectionFunctionExpression != null) {
       variableType = '';
       returnType = '';
     } else if (_returnType == null) {
       variableType = null;
       if (_hasAwait) {
-        returnType = _getTypeCode(futureType);
+        returnType = _getTypeCode(typeProvider.futureDynamicType);
       } else {
         returnType = 'void';
       }
     } else if (_returnType.isDynamic) {
       variableType = '';
       if (_hasAwait) {
-        returnType = _getTypeCode(futureType);
+        returnType = _getTypeCode(typeProvider.futureDynamicType);
       } else {
         returnType = '';
       }
     } else {
       variableType = _getTypeCode(_returnType);
       if (_hasAwait) {
-        if (_returnType.element != futureType.element) {
-          returnType = _getTypeCode(futureType.instantiate([_returnType]));
+        if (_returnType.element != typeProvider.futureElement) {
+          returnType = _getTypeCode(typeProvider.futureType2(_returnType));
         }
       } else {
         returnType = variableType;
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
index d9d3370..3feab8b 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
@@ -13,10 +13,12 @@
 import 'package:analysis_server/src/services/search/element_visitors.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analysis_server/src/utilities/flutter.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/analysis/session_helper.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
@@ -84,6 +86,12 @@
     return 'Extract Widget';
   }
 
+  FeatureSet get _featureSet {
+    return resolveResult.unit.featureSet;
+  }
+
+  bool get _isNonNullable => _featureSet.isEnabled(Feature.non_nullable);
+
   @override
   Future<RefactoringStatus> checkFinalConditions() async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
@@ -406,7 +414,10 @@
       builder.writeln();
       builder.writeClassDeclaration(
         name,
-        superclass: classStatelessWidget.type,
+        superclass: classStatelessWidget.instantiate(
+          typeArguments: const [],
+          nullabilitySuffix: NullabilitySuffix.none,
+        ),
         membersWriter: () {
           // Add the constructor.
           builder.write('  ');
@@ -418,7 +429,15 @@
 
               // Add the required `key` parameter.
               builder.write('    ');
-              builder.writeParameter('key', type: classKey.type);
+              builder.writeParameter(
+                'key',
+                type: classKey.instantiate(
+                  typeArguments: const [],
+                  nullabilitySuffix: _isNonNullable
+                      ? NullabilitySuffix.question
+                      : NullabilitySuffix.star,
+                ),
+              );
               builder.writeln(',');
 
               // Add parameters for fields, local, and method parameters.
@@ -471,9 +490,18 @@
           builder.write('  ');
           builder.writeFunctionDeclaration(
             'build',
-            returnType: classWidget.type,
+            returnType: classWidget.instantiate(
+              typeArguments: const [],
+              nullabilitySuffix: NullabilitySuffix.none,
+            ),
             parameterWriter: () {
-              builder.writeParameter('context', type: classBuildContext.type);
+              builder.writeParameter(
+                'context',
+                type: classBuildContext.instantiate(
+                  typeArguments: const [],
+                  nullabilitySuffix: NullabilitySuffix.none,
+                ),
+              );
             },
             bodyWriter: () {
               if (_expression != null) {
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 b487d2d..294ed47 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
@@ -393,8 +393,10 @@
         // "return" statement requires special handling
         if (lastStatement is ReturnStatement) {
           _methodExpression = lastStatement.expression;
-          SourceRange methodExpressionRange = range.node(_methodExpression);
-          _methodExpressionPart = _createSourcePart(methodExpressionRange);
+          if (_methodExpression != null) {
+            SourceRange methodExpressionRange = range.node(_methodExpression);
+            _methodExpressionPart = _createSourcePart(methodExpressionRange);
+          }
           // exclude "return" statement from statements
           statements = statements.sublist(0, statements.length - 1);
         }
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index 112ee48..e0b741a 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -31,7 +31,7 @@
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
 import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
-import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
diff --git a/pkg/analysis_server/lib/src/status/element_writer.dart b/pkg/analysis_server/lib/src/status/element_writer.dart
index a4a20c9..c91f46b 100644
--- a/pkg/analysis_server/lib/src/status/element_writer.dart
+++ b/pkg/analysis_server/lib/src/status/element_writer.dart
@@ -148,9 +148,6 @@
     if (element is PropertyInducingElement) {
       properties['isStatic'] = element.isStatic;
     }
-    if (element is TypeDefiningElement) {
-      properties['type'] = element.type;
-    }
     if (element is TypeParameterElement) {
       properties['bound'] = element.bound;
     }
diff --git a/pkg/analysis_server/pubspec.yaml b/pkg/analysis_server/pubspec.yaml
index 20a9e0e..0990d68 100644
--- a/pkg/analysis_server/pubspec.yaml
+++ b/pkg/analysis_server/pubspec.yaml
@@ -15,6 +15,7 @@
   linter: any
   logging: any
   meta: any
+  mustache: any
   nnbd_migration: any
   source_span: any
   package_config: any
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index 228ec3f..ad60430 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -20,7 +20,7 @@
 import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
 import 'package:analyzer/src/dart/analysis/session.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
diff --git a/pkg/analysis_server/test/domain_edit_dartfix_test.dart b/pkg/analysis_server/test/domain_edit_dartfix_test.dart
index 60c01fe..cabaf02 100644
--- a/pkg/analysis_server/test/domain_edit_dartfix_test.dart
+++ b/pkg/analysis_server/test/domain_edit_dartfix_test.dart
@@ -49,9 +49,9 @@
   }
 
   Future<EditDartfixResult> performFix(
-      {List<String> includedFixes, bool pedantic}) async {
-    var response =
-        await performFixRaw(includedFixes: includedFixes, pedantic: pedantic);
+      {List<String> includedFixes, String outputDir, bool pedantic}) async {
+    var response = await performFixRaw(
+        includedFixes: includedFixes, outputDir: outputDir, pedantic: pedantic);
     expect(response.error, isNull);
     return EditDartfixResult.fromResponse(response);
   }
@@ -59,11 +59,13 @@
   Future<Response> performFixRaw(
       {List<String> includedFixes,
       List<String> excludedFixes,
+      String outputDir,
       bool pedantic}) async {
     final id = nextRequestId;
     final params = new EditDartfixParams([projectPath]);
     params.includedFixes = includedFixes;
     params.excludedFixes = excludedFixes;
+    params.outputDir = outputDir;
     params.includePedanticFixes = pedantic;
     final request = new Request(id, 'edit.dartfix', params.toJson());
 
@@ -190,7 +192,7 @@
 ''');
   }
 
-  test_dartfix_non_nullable() async {
+  test_dartfix_nonNullable() async {
     // Add analysis options to enable non-nullable analysis
     newFile('/project/analysis_options.yaml', content: '''
 analyzer:
@@ -218,7 +220,7 @@
 ''');
   }
 
-  test_dartfix_non_nullable_analysis_options_created() async {
+  test_dartfix_nonNullable_analysisOptions_created() async {
     // Add pubspec for nnbd migration to detect
     newFile('/project/pubspec.yaml', content: '''
 name: testnnbd
@@ -237,7 +239,7 @@
 ''');
   }
 
-  test_dartfix_non_nullable_analysis_options_experiments_added() async {
+  test_dartfix_nonNullable_analysisOptions_experimentsAdded() async {
     String originalOptions = '''
 analyzer:
   something:
@@ -265,7 +267,7 @@
 ''');
   }
 
-  test_dartfix_non_nullable_analysis_options_nnbd_added() async {
+  test_dartfix_nonNullable_analysisOptions_nnbdAdded() async {
     String originalOptions = '''
 analyzer:
   enable-experiment:
@@ -290,6 +292,28 @@
 ''');
   }
 
+  test_dartfix_nonNullable_outputDir() async {
+    // Add analysis options to enable non-nullable analysis
+    newFile('/project/analysis_options.yaml', content: '''
+analyzer:
+  enable-experiment:
+    - non-nullable
+''');
+    addTestFile('''
+int f(int i) => 0;
+int g(int i) => f(i);
+void test() {
+  g(null);
+}
+''');
+    createProject();
+    var outputDir = getFolder('/outputDir');
+    await performFix(
+        includedFixes: ['non-nullable'], outputDir: outputDir.path);
+    expect(outputDir.exists, true);
+    expect(outputDir.getChildren(), isNotEmpty);
+  }
+
   test_dartfix_partFile() async {
     newFile('/project/lib/lib.dart', content: '''
 library lib2;
diff --git a/pkg/analysis_server/test/edit/fixes_test.dart b/pkg/analysis_server/test/edit/fixes_test.dart
index 37bb83e..efdb5d0 100644
--- a/pkg/analysis_server/test/edit/fixes_test.dart
+++ b/pkg/analysis_server/test/edit/fixes_test.dart
@@ -37,6 +37,7 @@
     addTestFile('''
 main() {
   Completer<String> x = null;
+  print(x);
 }
 ''');
     await waitForTasksFinished();
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
new file mode 100644
index 0000000..8695f99
--- /dev/null
+++ b/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.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.
+
+import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_renderer.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../analysis_abstract.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InstrumentationRendererTest);
+  });
+}
+
+@reflectiveTest
+class InstrumentationRendererTest extends AbstractAnalysisTest {
+  test_outputContainsModifiedAndUnmodifiedRegions() async {
+    LibraryInfo info = LibraryInfo([
+      UnitInfo('/lib/a.dart', 'int? a = null;',
+          [RegionInfo(3, 1, 'null was assigned')]),
+    ]);
+    String output = InstrumentationRenderer(info).render();
+    expect(
+        output,
+        contains('int<span class="region">?'
+            '<span class="tooltip">null was assigned</span></span> a = null;'));
+  }
+
+  test_outputContainsEachPath() async {
+    LibraryInfo info = LibraryInfo([
+      UnitInfo('/lib/a.dart', 'int? a = null;',
+          [RegionInfo(3, 1, 'null was assigned')]),
+      UnitInfo('/lib/part1.dart', 'int? b = null;',
+          [RegionInfo(3, 1, 'null was assigned')]),
+      UnitInfo('/lib/part2.dart', 'int? c = null;',
+          [RegionInfo(3, 1, 'null was assigned')]),
+    ]);
+    String output = InstrumentationRenderer(info).render();
+    expect(output, contains('<h2>&#x2F;lib&#x2F;a.dart</h2>'));
+    expect(output, contains('<h2>&#x2F;lib&#x2F;part1.dart</h2>'));
+    expect(output, contains('<h2>&#x2F;lib&#x2F;part2.dart</h2>'));
+  }
+}
diff --git a/pkg/analysis_server/test/edit/nnbd_migration/test_all.dart b/pkg/analysis_server/test/edit/nnbd_migration/test_all.dart
new file mode 100644
index 0000000..f02f07d
--- /dev/null
+++ b/pkg/analysis_server/test/edit/nnbd_migration/test_all.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.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'instrumentation_output_test.dart' as instrumentation_output;
+
+main() {
+  defineReflectiveSuite(() {
+    instrumentation_output.main();
+  }, name: 'nnbd_migration');
+}
diff --git a/pkg/analysis_server/test/edit/test_all.dart b/pkg/analysis_server/test/edit/test_all.dart
index 62595d3..1867550 100644
--- a/pkg/analysis_server/test/edit/test_all.dart
+++ b/pkg/analysis_server/test/edit/test_all.dart
@@ -7,6 +7,7 @@
 import 'assists_test.dart' as assists;
 import 'fixes_test.dart' as fixes;
 import 'format_test.dart' as format;
+import 'nnbd_migration/test_all.dart' as nnbd_migration;
 import 'organize_directives_test.dart' as organize_directives;
 import 'postfix_completion_test.dart' as postfix_completion;
 import 'refactoring_test.dart' as refactoring;
@@ -19,6 +20,7 @@
     assists.main();
     fixes.main();
     format.main();
+    nnbd_migration.main();
     organize_directives.main();
     postfix_completion.main();
     refactoring.main();
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 1440fe3..1425c1d 100644
--- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
@@ -1773,6 +1773,13 @@
    *   If a name is specified that does not match the name of a known fix, an
    *   error of type UNKNOWN_FIX will be generated.
    *
+   * outputDir: FilePath (optional)
+   *
+   *   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.
+   *
    * Returns
    *
    * suggestions: List<DartFixSuggestion>
@@ -1806,12 +1813,14 @@
       {List<String> includedFixes,
       bool includePedanticFixes,
       bool includeRequiredFixes,
-      List<String> excludedFixes}) async {
+      List<String> excludedFixes,
+      String outputDir}) async {
     var params = new EditDartfixParams(included,
             includedFixes: includedFixes,
             includePedanticFixes: includePedanticFixes,
             includeRequiredFixes: includeRequiredFixes,
-            excludedFixes: excludedFixes)
+            excludedFixes: excludedFixes,
+            outputDir: outputDir)
         .toJson();
     var result = await server.send("edit.dartfix", params);
     ResponseDecoder decoder = new ResponseDecoder(null);
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 61edec1..4fd9c45 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>
+ *   "outputDir": optional FilePath
  * }
  */
 final Matcher isEditDartfixParams =
@@ -2570,7 +2571,8 @@
           "includedFixes": isListOf(isString),
           "includePedanticFixes": isBool,
           "includeRequiredFixes": isBool,
-          "excludedFixes": isListOf(isString)
+          "excludedFixes": isListOf(isString),
+          "outputDir": isFilePath
         }));
 
 /**
diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
index c42a1b6..eb76db8 100644
--- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
@@ -4,6 +4,7 @@
 
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/keyword_contributor.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
@@ -52,227 +53,330 @@
     Keyword.TRUE,
   ];
 
-  List<Keyword> get classBodyKeywords => [
-        Keyword.CONST,
-        Keyword.COVARIANT,
-        Keyword.DYNAMIC,
-        Keyword.FACTORY,
-        Keyword.FINAL,
-        Keyword.GET,
-        Keyword.OPERATOR,
-        Keyword.SET,
-        Keyword.STATIC,
-        Keyword.VAR,
-        Keyword.VOID
-      ];
+  List<Keyword> get classBodyKeywords {
+    List<Keyword> keywords = [
+      Keyword.CONST,
+      Keyword.COVARIANT,
+      Keyword.DYNAMIC,
+      Keyword.FACTORY,
+      Keyword.FINAL,
+      Keyword.GET,
+      Keyword.OPERATOR,
+      Keyword.SET,
+      Keyword.STATIC,
+      Keyword.VAR,
+      Keyword.VOID
+    ];
+    if (isEnabled(ExperimentalFeatures.non_nullable)) {
+      keywords.add(Keyword.LATE);
+    }
+    return keywords;
+  }
 
-  List<Keyword> get constructorParameter => [Keyword.COVARIANT, Keyword.THIS];
+  List<Keyword> get constructorParameter {
+    List<Keyword> keywords = [Keyword.COVARIANT, Keyword.THIS];
+    if (isEnabled(ExperimentalFeatures.non_nullable)) {
+      keywords.add(Keyword.REQUIRED);
+    }
+    return keywords;
+  }
 
-  List<Keyword> get declarationKeywords => [
-        Keyword.ABSTRACT,
-        Keyword.CLASS,
-        Keyword.CONST,
-        Keyword.COVARIANT,
-        Keyword.DYNAMIC,
-        Keyword.FINAL,
-        Keyword.TYPEDEF,
-        Keyword.VAR,
-        Keyword.VOID
-      ];
+  List<Keyword> get declarationKeywords {
+    List<Keyword> keywords = [
+      Keyword.ABSTRACT,
+      Keyword.CLASS,
+      Keyword.CONST,
+      Keyword.COVARIANT,
+      Keyword.DYNAMIC,
+      Keyword.FINAL,
+      Keyword.TYPEDEF,
+      Keyword.VAR,
+      Keyword.VOID
+    ];
+    if (isEnabled(ExperimentalFeatures.extension_methods)) {
+      keywords.add(Keyword.EXTENSION);
+    }
+    if (isEnabled(ExperimentalFeatures.non_nullable)) {
+      keywords.add(Keyword.LATE);
+    }
+    return keywords;
+  }
 
-  List<Keyword> get directiveAndDeclarationKeywords => [
-        Keyword.ABSTRACT,
-        Keyword.CLASS,
-        Keyword.CONST,
-        Keyword.COVARIANT,
-        Keyword.DYNAMIC,
-        Keyword.EXPORT,
-        Keyword.FINAL,
-        Keyword.IMPORT,
-        Keyword.PART,
-        Keyword.TYPEDEF,
-        Keyword.VAR,
-        Keyword.VOID
-      ];
+  List<Keyword> get directiveAndDeclarationKeywords {
+    List<Keyword> keywords = [
+      Keyword.ABSTRACT,
+      Keyword.CLASS,
+      Keyword.CONST,
+      Keyword.COVARIANT,
+      Keyword.DYNAMIC,
+      Keyword.EXPORT,
+      Keyword.FINAL,
+      Keyword.IMPORT,
+      Keyword.PART,
+      Keyword.TYPEDEF,
+      Keyword.VAR,
+      Keyword.VOID
+    ];
+    if (isEnabled(ExperimentalFeatures.extension_methods)) {
+      keywords.add(Keyword.EXTENSION);
+    }
+    if (isEnabled(ExperimentalFeatures.non_nullable)) {
+      keywords.add(Keyword.LATE);
+    }
+    return keywords;
+  }
 
-  List<Keyword> get directiveDeclarationAndLibraryKeywords =>
-      directiveDeclarationKeywords..add(Keyword.LIBRARY);
+  List<Keyword> get directiveDeclarationAndLibraryKeywords {
+    List<Keyword> keywords = directiveDeclarationKeywords..add(Keyword.LIBRARY);
+    if (isEnabled(ExperimentalFeatures.non_nullable)) {
+      keywords.add(Keyword.LATE);
+    }
+    return keywords;
+  }
 
-  List<Keyword> get directiveDeclarationKeywords => [
-        Keyword.ABSTRACT,
-        Keyword.CLASS,
-        Keyword.CONST,
-        Keyword.COVARIANT,
-        Keyword.DYNAMIC,
-        Keyword.EXPORT,
-        Keyword.FINAL,
-        Keyword.IMPORT,
-        Keyword.PART,
-        Keyword.TYPEDEF,
-        Keyword.VAR,
-        Keyword.VOID
-      ];
+  List<Keyword> get directiveDeclarationKeywords {
+    List<Keyword> keywords = [
+      Keyword.ABSTRACT,
+      Keyword.CLASS,
+      Keyword.CONST,
+      Keyword.COVARIANT,
+      Keyword.DYNAMIC,
+      Keyword.EXPORT,
+      Keyword.FINAL,
+      Keyword.IMPORT,
+      Keyword.PART,
+      Keyword.TYPEDEF,
+      Keyword.VAR,
+      Keyword.VOID
+    ];
+    if (isEnabled(ExperimentalFeatures.extension_methods)) {
+      keywords.add(Keyword.EXTENSION);
+    }
+    if (isEnabled(ExperimentalFeatures.non_nullable)) {
+      keywords.add(Keyword.LATE);
+    }
+    return keywords;
+  }
 
-  List<Keyword> get methodParameter => [Keyword.COVARIANT];
+  List<Keyword> get methodParameter {
+    List<Keyword> keywords = [Keyword.COVARIANT];
+    if (isEnabled(ExperimentalFeatures.non_nullable)) {
+      keywords.add(Keyword.REQUIRED);
+    }
+    return keywords;
+  }
 
-  List<Keyword> get statementStartInClass => [
-        Keyword.ASSERT,
-        Keyword.CONST,
-        Keyword.DO,
-        Keyword.FINAL,
-        Keyword.FOR,
-        Keyword.IF,
-        Keyword.NEW,
-        Keyword.RETURN,
-        Keyword.SUPER,
-        Keyword.SWITCH,
-        Keyword.THIS,
-        Keyword.THROW,
-        Keyword.TRY,
-        Keyword.VAR,
-        Keyword.VOID,
-        Keyword.WHILE
-      ];
+  List<Keyword> get statementStartInClass {
+    List<Keyword> keywords = [
+      Keyword.ASSERT,
+      Keyword.CONST,
+      Keyword.DO,
+      Keyword.FINAL,
+      Keyword.FOR,
+      Keyword.IF,
+      Keyword.NEW,
+      Keyword.RETURN,
+      Keyword.SUPER,
+      Keyword.SWITCH,
+      Keyword.THIS,
+      Keyword.THROW,
+      Keyword.TRY,
+      Keyword.VAR,
+      Keyword.VOID,
+      Keyword.WHILE
+    ];
+    if (isEnabled(ExperimentalFeatures.non_nullable)) {
+      keywords.add(Keyword.LATE);
+    }
+    return keywords;
+  }
 
-  List<Keyword> get statementStartInLoopInClass => [
-        Keyword.ASSERT,
-        Keyword.BREAK,
-        Keyword.CONST,
-        Keyword.CONTINUE,
-        Keyword.DO,
-        Keyword.FINAL,
-        Keyword.FOR,
-        Keyword.IF,
-        Keyword.NEW,
-        Keyword.RETURN,
-        Keyword.SUPER,
-        Keyword.SWITCH,
-        Keyword.THIS,
-        Keyword.THROW,
-        Keyword.TRY,
-        Keyword.VAR,
-        Keyword.VOID,
-        Keyword.WHILE
-      ];
+  List<Keyword> get statementStartInLoopInClass {
+    List<Keyword> keywords = [
+      Keyword.ASSERT,
+      Keyword.BREAK,
+      Keyword.CONST,
+      Keyword.CONTINUE,
+      Keyword.DO,
+      Keyword.FINAL,
+      Keyword.FOR,
+      Keyword.IF,
+      Keyword.NEW,
+      Keyword.RETURN,
+      Keyword.SUPER,
+      Keyword.SWITCH,
+      Keyword.THIS,
+      Keyword.THROW,
+      Keyword.TRY,
+      Keyword.VAR,
+      Keyword.VOID,
+      Keyword.WHILE
+    ];
+    if (isEnabled(ExperimentalFeatures.non_nullable)) {
+      keywords.add(Keyword.LATE);
+    }
+    return keywords;
+  }
 
-  List<Keyword> get statementStartInLoopOutsideClass => [
-        Keyword.ASSERT,
-        Keyword.BREAK,
-        Keyword.CONST,
-        Keyword.CONTINUE,
-        Keyword.DO,
-        Keyword.FINAL,
-        Keyword.FOR,
-        Keyword.IF,
-        Keyword.NEW,
-        Keyword.RETURN,
-        Keyword.SWITCH,
-        Keyword.THROW,
-        Keyword.TRY,
-        Keyword.VAR,
-        Keyword.VOID,
-        Keyword.WHILE
-      ];
+  List<Keyword> get statementStartInLoopOutsideClass {
+    List<Keyword> keywords = [
+      Keyword.ASSERT,
+      Keyword.BREAK,
+      Keyword.CONST,
+      Keyword.CONTINUE,
+      Keyword.DO,
+      Keyword.FINAL,
+      Keyword.FOR,
+      Keyword.IF,
+      Keyword.NEW,
+      Keyword.RETURN,
+      Keyword.SWITCH,
+      Keyword.THROW,
+      Keyword.TRY,
+      Keyword.VAR,
+      Keyword.VOID,
+      Keyword.WHILE
+    ];
+    if (isEnabled(ExperimentalFeatures.non_nullable)) {
+      keywords.add(Keyword.LATE);
+    }
+    return keywords;
+  }
 
-  List<Keyword> get statementStartInSwitchCaseInClass => [
-        Keyword.ASSERT,
-        Keyword.BREAK,
-        Keyword.CONST,
-        Keyword.DO,
-        Keyword.FINAL,
-        Keyword.FOR,
-        Keyword.IF,
-        Keyword.NEW,
-        Keyword.RETURN,
-        Keyword.SUPER,
-        Keyword.THIS,
-        Keyword.SWITCH,
-        Keyword.THROW,
-        Keyword.TRY,
-        Keyword.VAR,
-        Keyword.VOID,
-        Keyword.WHILE
-      ];
+  List<Keyword> get statementStartInSwitchCaseInClass {
+    List<Keyword> keywords = [
+      Keyword.ASSERT,
+      Keyword.BREAK,
+      Keyword.CONST,
+      Keyword.DO,
+      Keyword.FINAL,
+      Keyword.FOR,
+      Keyword.IF,
+      Keyword.NEW,
+      Keyword.RETURN,
+      Keyword.SUPER,
+      Keyword.THIS,
+      Keyword.SWITCH,
+      Keyword.THROW,
+      Keyword.TRY,
+      Keyword.VAR,
+      Keyword.VOID,
+      Keyword.WHILE
+    ];
+    if (isEnabled(ExperimentalFeatures.non_nullable)) {
+      keywords.add(Keyword.LATE);
+    }
+    return keywords;
+  }
 
-  List<Keyword> get statementStartInSwitchCaseOutsideClass => [
-        Keyword.ASSERT,
-        Keyword.BREAK,
-        Keyword.CONST,
-        Keyword.DO,
-        Keyword.FINAL,
-        Keyword.FOR,
-        Keyword.IF,
-        Keyword.NEW,
-        Keyword.RETURN,
-        Keyword.SWITCH,
-        Keyword.THROW,
-        Keyword.TRY,
-        Keyword.VAR,
-        Keyword.VOID,
-        Keyword.WHILE
-      ];
+  List<Keyword> get statementStartInSwitchCaseOutsideClass {
+    List<Keyword> keywords = [
+      Keyword.ASSERT,
+      Keyword.BREAK,
+      Keyword.CONST,
+      Keyword.DO,
+      Keyword.FINAL,
+      Keyword.FOR,
+      Keyword.IF,
+      Keyword.NEW,
+      Keyword.RETURN,
+      Keyword.SWITCH,
+      Keyword.THROW,
+      Keyword.TRY,
+      Keyword.VAR,
+      Keyword.VOID,
+      Keyword.WHILE
+    ];
+    if (isEnabled(ExperimentalFeatures.non_nullable)) {
+      keywords.add(Keyword.LATE);
+    }
+    return keywords;
+  }
 
-  List<Keyword> get statementStartInSwitchInClass => [
-        Keyword.ASSERT,
-        Keyword.BREAK,
-        Keyword.CASE,
-        Keyword.CONST,
-        Keyword.DEFAULT,
-        Keyword.DO,
-        Keyword.FINAL,
-        Keyword.FOR,
-        Keyword.IF,
-        Keyword.NEW,
-        Keyword.RETURN,
-        Keyword.SUPER,
-        Keyword.SWITCH,
-        Keyword.THIS,
-        Keyword.THROW,
-        Keyword.TRY,
-        Keyword.VAR,
-        Keyword.VOID,
-        Keyword.WHILE
-      ];
+  List<Keyword> get statementStartInSwitchInClass {
+    List<Keyword> keywords = [
+      Keyword.ASSERT,
+      Keyword.BREAK,
+      Keyword.CASE,
+      Keyword.CONST,
+      Keyword.DEFAULT,
+      Keyword.DO,
+      Keyword.FINAL,
+      Keyword.FOR,
+      Keyword.IF,
+      Keyword.NEW,
+      Keyword.RETURN,
+      Keyword.SUPER,
+      Keyword.SWITCH,
+      Keyword.THIS,
+      Keyword.THROW,
+      Keyword.TRY,
+      Keyword.VAR,
+      Keyword.VOID,
+      Keyword.WHILE
+    ];
+    if (isEnabled(ExperimentalFeatures.non_nullable)) {
+      keywords.add(Keyword.LATE);
+    }
+    return keywords;
+  }
 
-  List<Keyword> get statementStartInSwitchOutsideClass => [
-        Keyword.ASSERT,
-        Keyword.BREAK,
-        Keyword.CASE,
-        Keyword.CONST,
-        Keyword.DEFAULT,
-        Keyword.DO,
-        Keyword.FINAL,
-        Keyword.FOR,
-        Keyword.IF,
-        Keyword.NEW,
-        Keyword.RETURN,
-        Keyword.SWITCH,
-        Keyword.THROW,
-        Keyword.TRY,
-        Keyword.VAR,
-        Keyword.VOID,
-        Keyword.WHILE
-      ];
+  List<Keyword> get statementStartInSwitchOutsideClass {
+    List<Keyword> keywords = [
+      Keyword.ASSERT,
+      Keyword.BREAK,
+      Keyword.CASE,
+      Keyword.CONST,
+      Keyword.DEFAULT,
+      Keyword.DO,
+      Keyword.FINAL,
+      Keyword.FOR,
+      Keyword.IF,
+      Keyword.NEW,
+      Keyword.RETURN,
+      Keyword.SWITCH,
+      Keyword.THROW,
+      Keyword.TRY,
+      Keyword.VAR,
+      Keyword.VOID,
+      Keyword.WHILE
+    ];
+    if (isEnabled(ExperimentalFeatures.non_nullable)) {
+      keywords.add(Keyword.LATE);
+    }
+    return keywords;
+  }
 
-  List<Keyword> get statementStartOutsideClass => [
-        Keyword.ASSERT,
-        Keyword.CONST,
-        Keyword.DO,
-        Keyword.FINAL,
-        Keyword.FOR,
-        Keyword.IF,
-        Keyword.NEW,
-        Keyword.RETURN,
-        Keyword.SWITCH,
-        Keyword.THROW,
-        Keyword.TRY,
-        Keyword.VAR,
-        Keyword.VOID,
-        Keyword.WHILE
-      ];
+  List<Keyword> get statementStartOutsideClass {
+    List<Keyword> keywords = [
+      Keyword.ASSERT,
+      Keyword.CONST,
+      Keyword.DO,
+      Keyword.FINAL,
+      Keyword.FOR,
+      Keyword.IF,
+      Keyword.NEW,
+      Keyword.RETURN,
+      Keyword.SWITCH,
+      Keyword.THROW,
+      Keyword.TRY,
+      Keyword.VAR,
+      Keyword.VOID,
+      Keyword.WHILE
+    ];
+    if (isEnabled(ExperimentalFeatures.non_nullable)) {
+      keywords.add(Keyword.LATE);
+    }
+    return keywords;
+  }
 
-  List<Keyword> get staticMember =>
-      [Keyword.CONST, Keyword.COVARIANT, Keyword.FINAL];
+  List<Keyword> get staticMember {
+    List<Keyword> keywords = [Keyword.CONST, Keyword.COVARIANT, Keyword.FINAL];
+    if (isEnabled(ExperimentalFeatures.non_nullable)) {
+      keywords.add(Keyword.LATE);
+    }
+    return keywords;
+  }
 
   void assertSuggestKeywords(Iterable<Keyword> expectedKeywords,
       {List<String> pseudoKeywords = NO_PSEUDO_KEYWORDS,
@@ -344,6 +448,10 @@
     return new KeywordContributor();
   }
 
+  /// Return `true` if the given [feature] is enabled.
+  bool isEnabled(Feature feature) =>
+      driver.analysisOptions.contextFeatures.isEnabled(feature);
+
   test_after_class_noPrefix() async {
     addTestSource('class A {} ^');
     await computeSuggestions();
@@ -2078,18 +2186,6 @@
 @reflectiveTest
 class KeywordContributorWithExtensionMethodsTest
     extends KeywordContributorTest {
-  @override
-  List<Keyword> get declarationKeywords =>
-      super.declarationKeywords..add(Keyword.EXTENSION);
-
-  @override
-  List<Keyword> get directiveAndDeclarationKeywords =>
-      super.directiveAndDeclarationKeywords..add(Keyword.EXTENSION);
-
-  @override
-  List<Keyword> get directiveDeclarationKeywords =>
-      super.directiveDeclarationKeywords..add(Keyword.EXTENSION);
-
   List<Keyword> get extensionBodyKeywords => [
         Keyword.CONST,
         Keyword.DYNAMIC,
@@ -2168,69 +2264,6 @@
 @reflectiveTest
 class KeywordContributorWithNnbdTest extends KeywordContributorTest {
   @override
-  List<Keyword> get classBodyKeywords =>
-      super.classBodyKeywords..add(Keyword.LATE);
-
-  @override
-  List<Keyword> get constructorParameter =>
-      super.constructorParameter..add(Keyword.REQUIRED);
-
-  @override
-  List<Keyword> get declarationKeywords =>
-      super.declarationKeywords..add(Keyword.LATE);
-
-  @override
-  List<Keyword> get directiveAndDeclarationKeywords =>
-      super.directiveAndDeclarationKeywords..add(Keyword.LATE);
-
-  @override
-  List<Keyword> get directiveDeclarationAndLibraryKeywords =>
-      super.directiveDeclarationAndLibraryKeywords..add(Keyword.LATE);
-
-  @override
-  List<Keyword> get directiveDeclarationKeywords =>
-      super.directiveDeclarationKeywords..add(Keyword.LATE);
-
-  @override
-  List<Keyword> get methodParameter =>
-      super.methodParameter..add(Keyword.REQUIRED);
-
-  @override
-  List<Keyword> get statementStartInClass =>
-      super.statementStartInClass..add(Keyword.LATE);
-
-  @override
-  List<Keyword> get statementStartInLoopInClass =>
-      super.statementStartInLoopInClass..add(Keyword.LATE);
-
-  @override
-  List<Keyword> get statementStartInLoopOutsideClass =>
-      super.statementStartInLoopOutsideClass..add(Keyword.LATE);
-
-  @override
-  List<Keyword> get statementStartInSwitchCaseInClass =>
-      super.statementStartInSwitchCaseInClass..add(Keyword.LATE);
-
-  @override
-  List<Keyword> get statementStartInSwitchCaseOutsideClass =>
-      super.statementStartInSwitchCaseOutsideClass..add(Keyword.LATE);
-
-  @override
-  List<Keyword> get statementStartInSwitchInClass =>
-      super.statementStartInSwitchInClass..add(Keyword.LATE);
-
-  @override
-  List<Keyword> get statementStartInSwitchOutsideClass =>
-      super.statementStartInSwitchOutsideClass..add(Keyword.LATE);
-
-  @override
-  List<Keyword> get statementStartOutsideClass =>
-      super.statementStartOutsideClass..add(Keyword.LATE);
-
-  @override
-  List<Keyword> get staticMember => super.staticMember..add(Keyword.LATE);
-
-  @override
   void setupResourceProvider() {
     super.setupResourceProvider();
     createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
diff --git a/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart
index 8e5f942..67c4a67 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart
@@ -4,6 +4,7 @@
 
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/local_library_contributor.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -12,6 +13,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(LocalLibraryContributorTest);
+    defineReflectiveTests(LocalLibraryContributorWithExtensionMethodsTest);
   });
 }
 
@@ -284,3 +286,29 @@
     assertNotSuggested('m');
   }
 }
+
+@reflectiveTest
+class LocalLibraryContributorWithExtensionMethodsTest
+    extends LocalLibraryContributorTest {
+  @override
+  void setupResourceProvider() {
+    super.setupResourceProvider();
+    createAnalysisOptionsFile(experiments: [EnableString.extension_methods]);
+  }
+
+  test_partFile_extension() async {
+    addSource('/home/test/lib/a.dart', '''
+part of libA;
+extension E on int {}
+''');
+    addTestSource('''
+library libA;
+part "a.dart";
+void f() {^}
+''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggest('E');
+  }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
index b91a939..083de60 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
@@ -4950,7 +4950,24 @@
     super.setUp();
   }
 
-  test_extensionDeclaration_body() async {
+  test_extensionDeclaration_inMethod() async {
+    // ExtensionDeclaration  CompilationUnit
+    addTestSource('''
+extension E on int {}
+class C {
+  void m() {
+    ^
+  }
+}
+''');
+    await computeSuggestions();
+
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggest('E');
+  }
+
+  test_extensionDeclaration_notInBody() async {
     // ExtensionDeclaration  CompilationUnit
     addSource('/home/test/lib/b.dart', '''
 class B { }''');
diff --git a/pkg/analysis_server/test/services/refactoring/inline_method_test.dart b/pkg/analysis_server/test/services/refactoring/inline_method_test.dart
index 061ba99..def1d78 100644
--- a/pkg/analysis_server/test/services/refactoring/inline_method_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/inline_method_test.dart
@@ -470,6 +470,27 @@
 ''');
   }
 
+  test_function_hasReturn_noExpression() async {
+    await indexTestUnit(r'''
+test(a, b) {
+  print(a);
+  print(b);
+  return;
+}
+main() {
+  test(1, 2);
+}
+''');
+    _createRefactoring('test(a, b)');
+    // validate change
+    return _assertSuccessfulRefactoring(r'''
+main() {
+  print(1);
+  print(2);
+}
+''');
+  }
+
   test_function_hasReturn_noVars_oneUsage() async {
     await indexTestUnit(r'''
 test(a, b) {
diff --git a/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart b/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart
index e99991e..33d5226 100644
--- a/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart
+++ b/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart
@@ -87,22 +87,6 @@
     _assertEmptyChange(result.change);
   }
 
-  test_invalid_label() async {
-    addTestFile(r'''
-import 'dart:math';
-
-main() {} // ref
-''');
-
-    var mathSet = await waitForSetWithUri('dart:math');
-
-    var response = await waitResponse(
-      _buildRequest(id: mathSet.id, label: 'foo', offset: 0),
-    );
-
-    expect(response.error.code, RequestErrorCode.INVALID_PARAMETER);
-  }
-
   test_invalid_library() async {
     addTestFile('');
 
diff --git a/pkg/analysis_server/test/src/services/correction/assist/add_not_null_assert.dart b/pkg/analysis_server/test/src/services/correction/assist/add_not_null_assert.dart
new file mode 100644
index 0000000..e39942c
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/assist/add_not_null_assert.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'assist_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(AddNotNullAssert);
+  });
+}
+
+@reflectiveTest
+class AddNotNullAssert extends AssistProcessorTest {
+  @override
+  AssistKind get kind => DartAssistKind.ADD_NOT_NULL_ASSERT;
+
+  test_function_expressionBody_noAssert() async {
+    await resolveTestUnit('''
+int double(int x) => x * 2;
+''');
+    // todo (pq): support expression bodies.
+    await assertNoAssistAt('x');
+  }
+
+  test_function_noAssert() async {
+    await resolveTestUnit('''
+foo(int x) {
+}
+''');
+    await assertHasAssistAt('x', '''
+foo(int x) {
+  assert(x != null);
+}
+''');
+  }
+
+  test_function_withAssert() async {
+    await resolveTestUnit('''
+foo(int x) {
+  assert(x != null);
+}
+''');
+    await assertNoAssistAt('x');
+  }
+
+  test_function_withAssert2() async {
+    await resolveTestUnit('''
+foo(int x) {
+  print('foo');
+  assert(x != null);
+}
+''');
+    await assertNoAssistAt('x');
+  }
+
+  test_method_noAssert() async {
+    await resolveTestUnit('''
+class A {
+  foo(int x) {
+  }
+}''');
+    await assertHasAssistAt('x', '''
+class A {
+  foo(int x) {
+    assert(x != null);
+  }
+}''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/inline_invocation_test.dart b/pkg/analysis_server/test/src/services/correction/assist/inline_invocation_test.dart
index a183e7f..8984a97 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/inline_invocation_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/inline_invocation_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer_plugin/utilities/assist/assist.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -34,6 +35,15 @@
 ''');
   }
 
+  test_add_emptyTarget_noAssistWithLint() async {
+    createAnalysisOptionsFile(lints: [LintNames.prefer_inlined_adds]);
+    verifyNoTestUnitErrors = false;
+    await resolveTestUnit('''
+var l = []..ad/*caret*/d('a')..add('b');
+''');
+    await assertNoAssist();
+  }
+
   test_add_nonEmptyTarget() async {
     await resolveTestUnit('''
 var l = ['a']..ad/*caret*/d('b')..add('c');
@@ -78,6 +88,15 @@
 ''');
   }
 
+  test_addAll_emptyTarget_noAssistWithLint() async {
+    createAnalysisOptionsFile(lints: [LintNames.prefer_inlined_adds]);
+    verifyNoTestUnitErrors = false;
+    await resolveTestUnit('''
+var l = []..add/*caret*/All(['a'])..addAll(['b']);
+''');
+    await assertNoAssist();
+  }
+
   test_addAll_nonEmptyTarget() async {
     await resolveTestUnit('''
 var l = ['a']..add/*caret*/All(['b'])..addAll(['c']);
diff --git a/pkg/analysis_server/test/src/services/correction/assist/sort_child_property_last_test.dart b/pkg/analysis_server/test/src/services/correction/assist/sort_child_property_last_test.dart
index 4cc5973..b8a4916 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/sort_child_property_last_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/sort_child_property_last_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
 import 'package:analyzer_plugin/utilities/assist/assist.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -97,4 +98,24 @@
 ''');
     assertExitPosition(after: "],");
   }
+
+  test_sort_noAssistWithLint() async {
+    addFlutterPackage();
+    createAnalysisOptionsFile(lints: [LintNames.sort_child_properties_last]);
+    verifyNoTestUnitErrors = false;
+    await resolveTestUnit('''
+import 'package:flutter/material.dart';
+main() {
+  Column(
+    /*caret*/children: <Widget>[
+      Text('aaa'),
+      Text('bbbbbb'),
+      Text('ccccccccc'),
+    ],
+    crossAxisAlignment: CrossAxisAlignment.center,
+  );
+}
+''');
+    await assertNoAssist();
+  }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
index b26ffb7..5580921 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
@@ -4,6 +4,7 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'add_not_null_assert.dart' as add_not_null_assert;
 import 'add_type_annotation_test.dart' as add_type_annotation;
 import 'assign_to_local_variable_test.dart' as assign_to_local_variable;
 import 'convert_class_to_mixin_test.dart' as convert_class_to_mixin;
@@ -82,6 +83,7 @@
 
 main() {
   defineReflectiveSuite(() {
+    add_not_null_assert.main();
     add_type_annotation.main();
     assign_to_local_variable.main();
     convert_class_to_mixin.main();
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_async_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_async_test.dart
index 4d4c30e..fe7ca89 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_async_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_async_test.dart
@@ -32,7 +32,7 @@
 ''');
     await assertHasFix('''
 import 'dart:async';
-Future main(Stream<String> names) async {
+Future<void> main(Stream<String> names) async {
   await for (String name in names) {
     print(name);
   }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_type_annotation_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_type_annotation_test.dart
index a7b406c..e54b689 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_type_annotation_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_type_annotation_test.dart
@@ -11,12 +11,13 @@
 
 main() {
   defineReflectiveSuite(() {
+    defineReflectiveTests(AddTypeAnnotationLintTest);
     defineReflectiveTests(AddTypeAnnotationTest);
   });
 }
 
 @reflectiveTest
-class AddTypeAnnotationTest extends FixProcessorLintTest {
+class AddTypeAnnotationLintTest extends FixProcessorLintTest {
   @override
   FixKind get kind => DartFixKind.ADD_TYPE_ANNOTATION;
 
@@ -37,3 +38,37 @@
 ''');
   }
 }
+
+@reflectiveTest
+class AddTypeAnnotationTest extends FixProcessorTest {
+  @override
+  FixKind get kind => DartFixKind.ADD_TYPE_ANNOTATION;
+
+  test_missingFieldType() async {
+    // MISSING_CONST_FINAL_VAR_OR_TYPE
+    await resolveTestUnit('''
+class A {
+  f = 0;
+}
+''');
+    await assertHasFix('''
+class A {
+  int f = 0;
+}
+''');
+  }
+
+  test_missingStaticFieldType() async {
+    // MISSING_CONST_FINAL_VAR_OR_TYPE
+    await resolveTestUnit('''
+class A {
+  static f = 0;
+}
+''');
+    await assertHasFix('''
+class A {
+  static int f = 0;
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/inline_invocation_test.dart b/pkg/analysis_server/test/src/services/correction/fix/inline_invocation_test.dart
new file mode 100644
index 0000000..b3c8344
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/inline_invocation_test.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:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InlineInvocationTest);
+  });
+}
+
+@reflectiveTest
+class InlineInvocationTest extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.INLINE_INVOCATION;
+
+  @override
+  String get lintCode => LintNames.prefer_inlined_adds;
+
+  /// More coverage in the `inline_invocation_test.dart` assist test.
+  test_add_emptyTarget() async {
+    await resolveTestUnit('''
+var l = []../*LINT*/add('a')..add('b');
+''');
+    await assertHasFix('''
+var l = ['a']..add('b');
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/qualify_reference_test.dart b/pkg/analysis_server/test/src/services/correction/fix/qualify_reference_test.dart
new file mode 100644
index 0000000..1184cb4
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/qualify_reference_test.dart
@@ -0,0 +1,242 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(QualifyReferenceTest);
+    defineReflectiveTests(QualifyReferenceWithExtensionMethodsTest);
+  });
+}
+
+@reflectiveTest
+class QualifyReferenceTest extends FixProcessorTest {
+  @override
+  FixKind get kind => DartFixKind.QUALIFY_REFERENCE;
+
+  test_class_direct() async {
+    await resolveTestUnit('''
+class C {
+  static void m() {}
+}
+class D extends C {
+  void f() {
+    m();
+  }
+}
+''');
+    await assertHasFix('''
+class C {
+  static void m() {}
+}
+class D extends C {
+  void f() {
+    C.m();
+  }
+}
+''');
+  }
+
+  test_class_imported() async {
+    newFile('/home/test/lib/a.dart', content: '''
+class A {
+  static void m() {}
+}
+''');
+    await resolveTestUnit('''
+import 'a.dart';
+class B extends A {
+  void f() {
+    m();
+  }
+}
+''');
+    await assertNoFix();
+  }
+
+  test_class_importedWithPrefix() async {
+    newFile('/home/test/lib/a.dart', content: '''
+class A {
+  static void m() {}
+}
+''');
+    await resolveTestUnit('''
+import 'a.dart' as a;
+class B extends a.A {
+  void f() {
+    m();
+  }
+}
+''');
+    await assertNoFix();
+  }
+
+  test_class_indirect() async {
+    await resolveTestUnit('''
+class A {
+  static void m() {}
+}
+class B extends A {}
+class C extends B {}
+class D extends C {
+  void f() {
+    m();
+  }
+}
+''');
+    await assertHasFix('''
+class A {
+  static void m() {}
+}
+class B extends A {}
+class C extends B {}
+class D extends C {
+  void f() {
+    A.m();
+  }
+}
+''');
+  }
+
+  test_class_notImported() async {
+    newFile('/home/test/lib/a.dart', content: '''
+class A {
+  static void m() {}
+}
+''');
+    newFile('/home/test/lib/b.dart', content: '''
+import 'a.dart';
+class B extends A {}
+''');
+    await resolveTestUnit('''
+import 'b.dart';
+class C extends B {
+  void f() {
+    m();
+  }
+}
+''');
+    await assertNoFix();
+  }
+}
+
+@reflectiveTest
+class QualifyReferenceWithExtensionMethodsTest extends QualifyReferenceTest {
+  @override
+  void setupResourceProvider() {
+    super.setupResourceProvider();
+    createAnalysisOptionsFile(experiments: [EnableString.extension_methods]);
+  }
+
+  test_extension_direct() async {
+    await resolveTestUnit('''
+class C {
+  static void m() {}
+}
+extension E on C {
+  void f() {
+    m();
+  }
+}
+''');
+    await assertHasFix('''
+class C {
+  static void m() {}
+}
+extension E on C {
+  void f() {
+    C.m();
+  }
+}
+''');
+  }
+
+  test_extension_imported() async {
+    newFile('/home/test/lib/a.dart', content: '''
+class A {
+  static void m() {}
+}
+''');
+    await resolveTestUnit('''
+import 'a.dart';
+extension E on A {
+  void f() {
+    m();
+  }
+}
+''');
+    await assertNoFix();
+  }
+
+  test_extension_importedWithPrefix() async {
+    newFile('/home/test/lib/a.dart', content: '''
+class A {
+  static void m() {}
+}
+''');
+    await resolveTestUnit('''
+import 'a.dart' as a;
+extension E on a.A {
+  void f() {
+    m();
+  }
+}
+''');
+    await assertNoFix();
+  }
+
+  test_extension_indirect() async {
+    await resolveTestUnit('''
+class A {
+  static void m() {}
+}
+class B extends A {}
+class C extends B {}
+extension E on C {
+  void f() {
+    m();
+  }
+}
+''');
+    await assertHasFix('''
+class A {
+  static void m() {}
+}
+class B extends A {}
+class C extends B {}
+extension E on C {
+  void f() {
+    A.m();
+  }
+}
+''');
+  }
+
+  test_extension_notImported() async {
+    newFile('/home/test/lib/a.dart', content: '''
+class A {
+  static void m() {}
+}
+''');
+    newFile('/home/test/lib/b.dart', content: '''
+import 'a.dart';
+class B extends A {}
+''');
+    await resolveTestUnit('''
+import 'b.dart';
+extension E on B {
+  void f() {
+    m();
+  }
+}
+''');
+    await assertNoFix();
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_element_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_element_test.dart
new file mode 100644
index 0000000..77d6f54
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_element_test.dart
@@ -0,0 +1,157 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RemoveUnusedElementTest);
+  });
+}
+
+@reflectiveTest
+class RemoveUnusedElementTest extends FixProcessorTest {
+  @override
+  FixKind get kind => DartFixKind.REMOVE_UNUSED_ELEMENT;
+
+  test_class_notUsed_inClassMember() async {
+    await resolveTestUnit(r'''
+class _A {
+  static staticMethod() {
+    new _A();
+  }
+}
+''');
+    // todo (pq): consider supporting the case where references are limited to within the class.
+    await assertNoFix();
+  }
+
+  test_class_notUsed_isExpression() async {
+    await resolveTestUnit(r'''
+class _A {}
+main(p) {
+  if (p is _A) {
+  }
+}
+''');
+    // We don't know what to do  with the reference.
+    await assertNoFix();
+  }
+
+  test_class_notUsed_noReference() async {
+    await resolveTestUnit(r'''
+class _A {
+}
+''');
+    await assertHasFix(r'''
+''');
+  }
+
+  test_enum_notUsed_noReference() async {
+    await resolveTestUnit(r'''
+enum _MyEnum {A, B, C}
+''');
+    await assertHasFix(r'''
+''');
+  }
+
+  test_functionLocal_notUsed_noReference() async {
+    await resolveTestUnit(r'''
+main() {
+  f() {}
+}
+''');
+    await assertHasFix(r'''
+main() {
+}
+''');
+  }
+
+  test_functionTop_notUsed_noReference() async {
+    await resolveTestUnit(r'''
+_f() {}
+main() {
+}
+''');
+    await assertHasFix(r'''
+main() {
+}
+''');
+  }
+
+  test_functionTypeAlias_notUsed_noReference() async {
+    await resolveTestUnit(r'''
+typedef _F(a, b);
+main() {
+}
+''');
+    await assertHasFix(r'''
+main() {
+}
+''');
+  }
+
+  test_getter_notUsed_noReference() async {
+    await resolveTestUnit(r'''
+class A {
+  get _g => null;
+}
+''');
+    await assertHasFix(r'''
+class A {
+}
+''');
+  }
+
+  test_method_notUsed_noReference() async {
+    await resolveTestUnit(r'''
+class A {
+  static _m() {}
+}
+''');
+    await assertHasFix(r'''
+class A {
+}
+''');
+  }
+
+  test_setter_notUsed_noReference() async {
+    await resolveTestUnit(r'''
+class A {
+  set _s(x) {}
+}
+''');
+    await assertHasFix(r'''
+class A {
+}
+''');
+  }
+
+  test_topLevelVariable_notUsed() async {
+    await resolveTestUnit(r'''
+int _a = 1;
+main() {
+  _a = 2;
+}
+''');
+    // Reference.
+    await assertNoFix();
+  }
+
+  test_topLevelVariable_notUsed_noReference() async {
+    await resolveTestUnit(r'''
+int _a = 1;
+main() {
+}
+''');
+    await assertHasFix(r'''
+main() {
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_field_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_field_test.dart
new file mode 100644
index 0000000..a398ef8
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_field_test.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.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RemoveUnusedFieldTest);
+  });
+}
+
+@reflectiveTest
+class RemoveUnusedFieldTest extends FixProcessorTest {
+  @override
+  FixKind get kind => DartFixKind.REMOVE_UNUSED_FIELD;
+
+  test_unusedField_notUsed_assign() async {
+    await resolveTestUnit(r'''
+class A {
+  int _f;
+  main() {
+    _f = 2;
+  }
+}
+''');
+    await assertHasFix(r'''
+class A {
+  main() {
+  }
+}
+''');
+  }
+
+  test_unusedField_notUsed_compoundAssign() async {
+    await resolveTestUnit(r'''
+class A {
+  int _f;
+  main() {
+    _f += 2;
+  }
+}
+''');
+    await assertHasFix(r'''
+class A {
+  main() {
+  }
+}
+''');
+  }
+
+  test_unusedField_notUsed_constructorFieldInitializers() async {
+    await resolveTestUnit(r'''
+class A {
+  int _f;
+  A() : _f = 0;
+}
+''');
+    await assertHasFix(r'''
+class A {
+  A();
+}
+''');
+  }
+
+  test_unusedField_notUsed_constructorFieldInitializers1() async {
+    await resolveTestUnit(r'''
+class A {
+  int _f;
+  int y;
+  A() : _f = 0, y = 1;
+}
+''');
+    await assertHasFix(r'''
+class A {
+  int y;
+  A() : y = 1;
+}
+''');
+  }
+
+  test_unusedField_notUsed_constructorFieldInitializers2() async {
+    await resolveTestUnit(r'''
+class A {
+  int _f;
+  int y;
+  A() : y = 1, _f = 0;
+}
+''');
+    await assertHasFix(r'''
+class A {
+  int y;
+  A() : y = 1;
+}
+''');
+  }
+
+  test_unusedField_notUsed_declarationList() async {
+    await resolveTestUnit(r'''
+class A {
+  int _f, x;
+  A(this._f) {
+    print(x);
+  }
+}
+''');
+    await assertHasFix(r'''
+class A {
+  int x;
+  A() {
+    print(x);
+  }
+}
+''');
+  }
+
+  test_unusedField_notUsed_declarationList2() async {
+    await resolveTestUnit(r'''
+class A {
+  int x, _f;
+  A(this._f) {
+    print(x);
+  }
+}
+''');
+    await assertHasFix(r'''
+class A {
+  int x;
+  A() {
+    print(x);
+  }
+}
+''');
+  }
+
+  test_unusedField_notUsed_fieldFormalParameter() async {
+    await resolveTestUnit(r'''
+class A {
+  int _f;
+  A(this._f);
+}
+''');
+    await assertHasFix(r'''
+class A {
+  A();
+}
+''');
+  }
+
+  test_unusedField_notUsed_fieldFormalParameter2() async {
+    await resolveTestUnit(r'''
+class A {
+  int _f;
+  int x;
+  A(this._f, this.x);
+}
+''');
+    await assertHasFix(r'''
+class A {
+  int x;
+  A(this.x);
+}
+''');
+  }
+
+  test_unusedField_notUsed_fieldFormalParameter3() async {
+    await resolveTestUnit(r'''
+class A {
+  int x;
+  int _f;
+  A(this.x, this._f);
+}
+''');
+    await assertHasFix(r'''
+class A {
+  int x;
+  A(this.x);
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_label_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_label_test.dart
new file mode 100644
index 0000000..3b0f339
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_label_test.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RemoveUnusedLabelTest);
+  });
+}
+
+@reflectiveTest
+class RemoveUnusedLabelTest extends FixProcessorTest {
+  @override
+  FixKind get kind => DartFixKind.REMOVE_UNUSED_LABEL;
+
+  test_unused_onWhile() async {
+    await resolveTestUnit('''
+f() {
+  x:
+  while (true) {
+    break;
+  }
+}
+''');
+    await assertHasFix('''
+f() {
+  while (true) {
+    break;
+  }
+}
+''');
+  }
+
+  test_unused_onWhile_sameLine() async {
+    await resolveTestUnit('''
+f() {
+  x: while (true) {
+    break;
+  }
+}
+''');
+    await assertHasFix('''
+f() {
+  while (true) {
+    break;
+  }
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_local_variable_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_local_variable_test.dart
new file mode 100644
index 0000000..c05e4cc
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_local_variable_test.dart
@@ -0,0 +1,129 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RemoveUnusedLocalVariableTest);
+  });
+}
+
+@reflectiveTest
+class RemoveUnusedLocalVariableTest extends FixProcessorTest {
+  @override
+  FixKind get kind => DartFixKind.REMOVE_UNUSED_LOCAL_VARIABLE;
+
+  test_inArgumentList() async {
+    await resolveTestUnit(r'''
+main() {
+  var v = 1;
+  print(v = 2);
+}
+''');
+    await assertHasFix(r'''
+main() {
+  print(2);
+}
+''');
+  }
+
+  test_inArgumentList2() async {
+    await resolveTestUnit(r'''
+main() {
+  var v = 1;
+  f(v = 1, 2);
+}
+void f(a, b) { }
+''');
+    await assertHasFix(r'''
+main() {
+  f(1, 2);
+}
+void f(a, b) { }
+''');
+  }
+
+  test_inArgumentList3() async {
+    await resolveTestUnit(r'''
+main() {
+  var v = 1;
+  f(v = 1, v = 2);
+}
+void f(a, b) { }
+''');
+    await assertHasFix(r'''
+main() {
+  f(1, 2);
+}
+void f(a, b) { }
+''');
+  }
+
+  test_inDeclarationList() async {
+    await resolveTestUnit(r'''
+main() {
+  var v = 1, v2 = 3;
+  v = 2;
+  print(v2);
+}
+''');
+    await assertHasFix(r'''
+main() {
+  var v2 = 3;
+  print(v2);
+}
+''');
+  }
+
+  test_inDeclarationList2() async {
+    await resolveTestUnit(r'''
+main() {
+  var v = 1, v2 = 3;
+  print(v);
+}
+''');
+    await assertHasFix(r'''
+main() {
+  var v = 1;
+  print(v);
+}
+''');
+  }
+
+  test_withReferences() async {
+    await resolveTestUnit(r'''
+main() {
+  var v = 1;
+  v = 2;
+}
+''');
+    await assertHasFix(r'''
+main() {
+}
+''');
+  }
+
+  test_withReferences_beforeDeclaration() async {
+    // CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION
+    verifyNoTestUnitErrors = false;
+    await resolveTestUnit(r'''
+main() {
+  v = 2;
+  var v = 1;
+}
+''');
+    await assertHasFix(r'''
+main() {
+}
+''',
+        errorFilter: (e) =>
+            e.errorCode != CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION);
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_with_extension_name_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_with_extension_name_test.dart
new file mode 100644
index 0000000..b31de86
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_with_extension_name_test.dart
@@ -0,0 +1,113 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ReplaceWithExtensionNameTest);
+  });
+}
+
+@reflectiveTest
+class ReplaceWithExtensionNameTest extends FixProcessorTest {
+  @override
+  FixKind get kind => DartFixKind.REPLACE_WITH_EXTENSION_NAME;
+
+  @override
+  void setupResourceProvider() {
+    super.setupResourceProvider();
+    createAnalysisOptionsFile(experiments: [EnableString.extension_methods]);
+  }
+
+  test_getter() async {
+    await resolveTestUnit('''
+extension E on String {
+  static int get g => 0;
+}
+
+void f() {
+  E('a').g;
+}
+''');
+    await assertHasFix('''
+extension E on String {
+  static int get g => 0;
+}
+
+void f() {
+  E.g;
+}
+''');
+  }
+
+  test_method() async {
+    await resolveTestUnit('''
+extension E on String {
+  static int m() => 0;
+}
+
+void f() {
+  E('a').m();
+}
+''');
+    await assertHasFix('''
+extension E on String {
+  static int m() => 0;
+}
+
+void f() {
+  E.m();
+}
+''');
+  }
+
+  test_qualified() async {
+    newFile('/home/test/lib/ext.dart', content: '''
+extension E on String {
+  static int m() => 0;
+}
+''');
+    await resolveTestUnit('''
+import 'ext.dart' as ext;
+
+void f() {
+  ext.E('a').m();
+}
+''');
+    await assertHasFix('''
+import 'ext.dart' as ext;
+
+void f() {
+  ext.E.m();
+}
+''');
+  }
+
+  test_setter() async {
+    await resolveTestUnit('''
+extension E on String {
+  static set s(int i) {}
+}
+
+void f() {
+  E('a').s = 3;
+}
+''');
+    await assertHasFix('''
+extension E on String {
+  static set s(int i) {}
+}
+
+void f() {
+  E.s = 3;
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/sort_child_property_last_test.dart b/pkg/analysis_server/test/src/services/correction/fix/sort_child_property_last_test.dart
new file mode 100644
index 0000000..9a7ca7c
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/sort_child_property_last_test.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(SortChildPropertiesLastTest);
+  });
+}
+
+@reflectiveTest
+class SortChildPropertiesLastTest extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.SORT_CHILD_PROPERTY_LAST;
+
+  @override
+  String get lintCode => LintNames.sort_child_properties_last;
+
+  /// More coverage in the `sort_child_properties_last_test.dart` assist test.
+  test_sort() async {
+    addFlutterPackage();
+    await resolveTestUnit('''
+import 'package:flutter/material.dart';
+main() {
+  Column(
+    /*LINT*/children: <Widget>[
+      Text('aaa'),
+      Text('bbbbbb'),
+      Text('ccccccccc'),
+    ],
+    crossAxisAlignment: CrossAxisAlignment.center,
+  );
+}
+''');
+    await assertHasFix('''
+import 'package:flutter/material.dart';
+main() {
+  Column(
+    crossAxisAlignment: CrossAxisAlignment.center,
+    /*LINT*/children: <Widget>[
+      Text('aaa'),
+      Text('bbbbbb'),
+      Text('ccccccccc'),
+    ],
+  );
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
index 4e74718..3509418 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -69,12 +69,14 @@
 import 'import_library_project_test.dart' as import_library_project;
 import 'import_library_sdk_test.dart' as import_library_sdk;
 import 'import_library_show_test.dart' as import_library_show;
+import 'inline_invocation_test.dart' as inline_invocation;
 import 'insert_semicolon_test.dart' as insert_semicolon;
 import 'make_class_abstract_test.dart' as make_class_abstract;
 import 'make_field_not_final_test.dart' as make_field_not_final;
 import 'make_final_test.dart' as make_final;
 import 'make_variable_not_final_test.dart' as make_variable_not_final;
 import 'move_type_arguments_to_class_test.dart' as move_type_arguments_to_class;
+import 'qualify_reference_test.dart' as qualify_reference;
 import 'remove_annotation_test.dart' as remove_annotation;
 import 'remove_await_test.dart' as remove_await;
 import 'remove_dead_code_test.dart' as remove_dead_code;
@@ -100,7 +102,11 @@
 import 'remove_unnecessary_new_test.dart' as remove_unnecessary_new;
 import 'remove_unused_catch_clause_test.dart' as remove_unused_catch_clause;
 import 'remove_unused_catch_stack_test.dart' as remove_unused_catch_stack;
+import 'remove_unused_element_test.dart' as remove_unused_element;
+import 'remove_unused_field_test.dart' as remove_unused_field;
 import 'remove_unused_import_test.dart' as remove_unused_import;
+import 'remove_unused_label_test.dart' as remove_unused_label;
+import 'remove_unused_local_variable_test.dart' as remove_unused_local_variable;
 import 'rename_to_camel_case_test.dart' as rename_to_camel_case;
 import 'replace_boolean_with_bool_test.dart' as replace_boolean_with_bool;
 import 'replace_colon_with_equals_test.dart' as replace_colon_with_equals;
@@ -112,11 +118,13 @@
 import 'replace_with_brackets_test.dart' as replace_with_brackets;
 import 'replace_with_conditional_assignment_test.dart'
     as replace_with_conditional_assignment;
+import 'replace_with_extension_name_test.dart' as replace_with_extension_name;
 import 'replace_with_identifier_test.dart' as replace_with_identifier;
 import 'replace_with_is_empty_test.dart' as replace_with_is_empty;
 import 'replace_with_is_not_empty_test.dart' as replace_with_is_not_empty;
 import 'replace_with_null_aware_test.dart' as replace_with_null_aware;
 import 'replace_with_tear_off_test.dart' as replace_with_tear_off;
+import 'sort_child_property_last_test.dart' as sort_properties_last;
 import 'update_sdk_constraints_test.dart' as update_sdk_constraints;
 import 'use_const_test.dart' as use_const;
 import 'use_effective_integer_division_test.dart'
@@ -184,12 +192,14 @@
     import_library_project.main();
     import_library_sdk.main();
     import_library_show.main();
+    inline_invocation.main();
     insert_semicolon.main();
     make_class_abstract.main();
     make_field_not_final.main();
     make_final.main();
     make_variable_not_final.main();
     move_type_arguments_to_class.main();
+    qualify_reference.main();
     remove_annotation.main();
     remove_await.main();
     remove_dead_code.main();
@@ -212,7 +222,11 @@
     remove_unnecessary_new.main();
     remove_unused_catch_clause.main();
     remove_unused_catch_stack.main();
+    remove_unused_element.main();
+    remove_unused_field.main();
     remove_unused_import.main();
+    remove_unused_label.main();
+    remove_unused_local_variable.main();
     rename_to_camel_case.main();
     replace_boolean_with_bool.main();
     replace_colon_with_equals.main();
@@ -223,11 +237,13 @@
     replace_var_with_dynamic.main();
     replace_with_brackets.main();
     replace_with_conditional_assignment.main();
+    replace_with_extension_name.main();
     replace_with_identifier.main();
     replace_with_is_empty.main();
     replace_with_is_not_empty.main();
     replace_with_null_aware.main();
     replace_with_tear_off.main();
+    sort_properties_last.main();
     update_sdk_constraints.main();
     use_const.main();
     use_effective_integer_division.main();
diff --git a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
index 4132f31..f4e3170 100644
--- a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
+++ b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
@@ -498,8 +498,12 @@
    * @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 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, DartfixConsumer consumer);
+  public void edit_dartfix(List<String> included, List<String> includedFixes, boolean includePedanticFixes, boolean includeRequiredFixes, List<String> excludedFixes, 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 712bdc4..f74c90d 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -2235,6 +2235,16 @@
           an error of type <tt>UNKNOWN_FIX</tt> will be generated.
         </p>
       </field>
+      <field name="outputDir" optional="true">
+        <ref>FilePath</ref>
+        <p>
+          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.
+        </p>
+      </field>
     </params>
     <result>
       <field name="suggestions">
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 686011c..55a6571 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
@@ -172,6 +172,7 @@
     'includePedanticFixes';
 const String EDIT_REQUEST_DARTFIX_INCLUDE_REQUIRED_FIXES =
     'includeRequiredFixes';
+const String EDIT_REQUEST_DARTFIX_OUTPUT_DIR = 'outputDir';
 const String EDIT_REQUEST_FORMAT = 'edit.format';
 const String EDIT_REQUEST_FORMAT_FILE = 'file';
 const String EDIT_REQUEST_FORMAT_LINE_LENGTH = 'lineLength';
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 d0c24a3..e0495b8 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>
+ *   "outputDir": optional FilePath
  * }
  *
  * Clients may not extend, implement or mix-in this class.
@@ -7979,6 +7980,8 @@
 
   List<String> _excludedFixes;
 
+  String _outputDir;
+
   /**
    * A list of the files and directories for which edits should be suggested.
    *
@@ -8066,16 +8069,36 @@
     this._excludedFixes = 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,
+   * but no previously existing files will be deleted.
+   */
+  String get outputDir => _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.
+   */
+  void set outputDir(String value) {
+    this._outputDir = value;
+  }
+
   EditDartfixParams(List<String> included,
       {List<String> includedFixes,
       bool includePedanticFixes,
       bool includeRequiredFixes,
-      List<String> excludedFixes}) {
+      List<String> excludedFixes,
+      String outputDir}) {
     this.included = included;
     this.includedFixes = includedFixes;
     this.includePedanticFixes = includePedanticFixes;
     this.includeRequiredFixes = includeRequiredFixes;
     this.excludedFixes = excludedFixes;
+    this.outputDir = outputDir;
   }
 
   factory EditDartfixParams.fromJson(
@@ -8111,11 +8134,17 @@
         excludedFixes = jsonDecoder.decodeList(jsonPath + ".excludedFixes",
             json["excludedFixes"], jsonDecoder.decodeString);
       }
+      String outputDir;
+      if (json.containsKey("outputDir")) {
+        outputDir = jsonDecoder.decodeString(
+            jsonPath + ".outputDir", json["outputDir"]);
+      }
       return new EditDartfixParams(included,
           includedFixes: includedFixes,
           includePedanticFixes: includePedanticFixes,
           includeRequiredFixes: includeRequiredFixes,
-          excludedFixes: excludedFixes);
+          excludedFixes: excludedFixes,
+          outputDir: outputDir);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "edit.dartfix params", json);
     }
@@ -8142,6 +8171,9 @@
     if (excludedFixes != null) {
       result["excludedFixes"] = excludedFixes;
     }
+    if (outputDir != null) {
+      result["outputDir"] = outputDir;
+    }
     return result;
   }
 
@@ -8163,7 +8195,8 @@
           includePedanticFixes == other.includePedanticFixes &&
           includeRequiredFixes == other.includeRequiredFixes &&
           listEqual(excludedFixes, other.excludedFixes,
-              (String a, String b) => a == b);
+              (String a, String b) => a == b) &&
+          outputDir == other.outputDir;
     }
     return false;
   }
@@ -8176,6 +8209,7 @@
     hash = JenkinsSmiHash.combine(hash, includePedanticFixes.hashCode);
     hash = JenkinsSmiHash.combine(hash, includeRequiredFixes.hashCode);
     hash = JenkinsSmiHash.combine(hash, excludedFixes.hashCode);
+    hash = JenkinsSmiHash.combine(hash, outputDir.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 }
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 6c308d7..04cd0e5 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,18 @@
+## 0.38.3
+* Deprecated the following codes from `StaticWarningCode`.  Please use the
+  corresponding error codes from `CompileTimeErrorCode` instead:
+  * `EXTRA_POSITIONAL_ARGUMENTS`
+  * `EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED`
+  * `IMPORT_OF_NON_LIBRARY`
+  * `NOT_ENOUGH_REQUIRED_ARGUMENTS`
+  * `REDIRECT_TO_MISSING_CONSTRUCTOR`
+  * `REDIRECT_TO_NON_CLASS`
+  * `UNDEFINED_CLASS`
+  * `UNDEFINED_NAMED_PARAMETER`
+* Bug fixes: #33749, #35985, #37708, #37857, #37858, #37859, #37945, #38022,
+  #38057, #38071, #38091, #38095, #38105, #38113, #38198, #38202, #38203,
+  #38261, #38282, #38365, #38417, #38448, #38449.
+
 ## 0.38.2
 * The type of `FunctionTypeAlias.declaredElement` has been refined to
   `FunctionTypeAliasElement`.  Since the new type is a refinement of
diff --git a/pkg/analyzer/lib/dart/analysis/analysis_context.dart b/pkg/analyzer/lib/dart/analysis/analysis_context.dart
index 6c3728f..3a77423 100644
--- a/pkg/analyzer/lib/dart/analysis/analysis_context.dart
+++ b/pkg/analyzer/lib/dart/analysis/analysis_context.dart
@@ -4,7 +4,7 @@
 
 import 'package:analyzer/dart/analysis/context_root.dart';
 import 'package:analyzer/dart/analysis/session.dart';
-import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
+import 'package:analyzer/src/generated/engine.dart';
 
 /// A representation of a body of code and the context in which the code is to
 /// be analyzed.
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 02fdde9..6bfb473 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -3303,6 +3303,9 @@
   /// ancestor that is a [CascadeExpression].
   bool get isCascaded;
 
+  /// Whether this index expression is null aware (as opposed to non-null).
+  bool get isNullAware;
+
   /// Return the left square bracket.
   Token get leftBracket;
 
@@ -3863,6 +3866,9 @@
   /// ancestor that is a [CascadeExpression].
   bool get isCascaded;
 
+  /// Whether this method invocation is null aware (as opposed to non-null).
+  bool get isNullAware;
+
   /// Return the name of the method being invoked.
   SimpleIdentifier get methodName;
 
@@ -4411,6 +4417,9 @@
   /// ancestor that is a [CascadeExpression].
   bool get isCascaded;
 
+  /// Whether this property access is null aware (as opposed to non-null).
+  bool get isNullAware;
+
   /// Return the property access operator.
   Token get operator;
 
@@ -4786,11 +4795,11 @@
   /// The expression used to compute the collection being spread.
   Expression get expression;
 
-  /// The spread operator, either '...' or '...?'.
-  Token get spreadOperator;
-
   /// Whether this is a null-aware spread, as opposed to a non-null spread.
   bool get isNullAware;
+
+  /// The spread operator, either '...' or '...?'.
+  Token get spreadOperator;
 }
 
 /// A node that represents a statement.
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 0eda2b3..8ae0ba1 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -37,6 +37,7 @@
 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';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/dart/constant/evaluation.dart';
@@ -101,6 +102,10 @@
   /// <i>abstract</i> is different from <i>has unimplemented members</i>.
   bool get isAbstract;
 
+  /// Return `true` if this class represents the class 'Object' defined in the
+  /// dart:core library.
+  bool get isDartCoreObject;
+
   /// Return `true` if this class is defined by an enum declaration.
   bool get isEnum;
 
@@ -170,6 +175,15 @@
   /// guard against infinite loops.
   InterfaceType get supertype;
 
+  /// Return the type of `this` expression for this class.
+  ///
+  /// For a class like `class MyClass<T, U> {}` the returned type is equivalent
+  /// to the type `MyClass<T, U>`. So, the type arguments are the types of the
+  /// type parameters, and either `none` or `star` nullability suffix is used
+  /// for the type arguments, and the returned type depending on the
+  /// nullability status of the declaring library.
+  InterfaceType get thisType;
+
   @override
   InterfaceType get type;
 
@@ -210,6 +224,13 @@
   /// with the given name.
   PropertyAccessorElement getSetter(String name);
 
+  /// Create the [InterfaceType] for this class with the given [typeArguments]
+  /// and [nullabilitySuffix].
+  InterfaceType instantiate({
+    @required List<DartType> typeArguments,
+    @required NullabilitySuffix nullabilitySuffix,
+  });
+
   /// Return the element representing the method that results from looking up
   /// the given [methodName] in this class with respect to the given [library],
   /// ignoring abstract methods, or `null` if the look up fails. The behavior of
@@ -1187,6 +1208,19 @@
   /// then a single type argument should be provided, and it will be substituted
   /// for T.
   FunctionType instantiate(List<DartType> argumentTypes);
+
+  /// Produces the function type resulting from instantiating this typedef with
+  /// the given [typeArguments] and [nullabilitySuffix].
+  ///
+  /// 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 `F<int>` will produce `void Function<U>(int, U)`.
+  FunctionType instantiate2({
+    @required List<DartType> typeArguments,
+    @required NullabilitySuffix nullabilitySuffix,
+  });
 }
 
 /// An element that has a [FunctionType] as its [type].
@@ -1656,6 +1690,12 @@
 
   @override
   TypeParameterType get type;
+
+  /// Create the [TypeParameterType] with the given [nullabilitySuffix] for
+  /// this type parameter.
+  TypeParameterType instantiate({
+    @required NullabilitySuffix nullabilitySuffix,
+  });
 }
 
 /// An element that has type parameters, such as a class or a typedef. This also
diff --git a/pkg/analyzer/lib/dart/element/nullability_suffix.dart b/pkg/analyzer/lib/dart/element/nullability_suffix.dart
new file mode 100644
index 0000000..59a7759
--- /dev/null
+++ b/pkg/analyzer/lib/dart/element/nullability_suffix.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.
+
+/// Suffix indicating the nullability of a type.
+///
+/// This enum describes whether a `?` or `*` would be used at the end of the
+/// canonical representation of a type.  It's subtly different the notions of
+/// "nullable", "non-nullable", "potentially nullable", and "potentially
+/// non-nullable" defined by the spec.  For example, the type `Null` is
+/// nullable, even though it lacks a trailing `?`.
+enum NullabilitySuffix {
+  /// An indication that the canonical representation of the type under
+  /// consideration ends with `?`.  Types having this nullability suffix should
+  /// be interpreted as being unioned with the Null type.
+  question,
+
+  /// An indication that the canonical representation of the type under
+  /// consideration ends with `*`.  Types having this nullability suffix are
+  /// called "legacy types"; it has not yet been determined whether they should
+  /// be unioned with the Null type.
+  star,
+
+  /// An indication that the canonical representation of the type under
+  /// consideration does not end with either `?` or `*`.
+  none
+}
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 94175cc..0dfe3fa 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -142,6 +142,7 @@
   CompileTimeErrorCode.EXTENSION_DECLARES_MEMBER_OF_OBJECT,
   CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER,
   CompileTimeErrorCode.EXTENSION_OVERRIDE_ARGUMENT_NOT_ASSIGNABLE,
+  CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE,
   CompileTimeErrorCode.EXTENSION_OVERRIDE_WITHOUT_ACCESS,
   CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS,
   CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED,
@@ -304,6 +305,7 @@
   CompileTimeErrorCode.UNDEFINED_EXTENSION_METHOD,
   CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER,
   CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER,
+  CompileTimeErrorCode.UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE,
   CompileTimeErrorCode.URI_DOES_NOT_EXIST,
   CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED,
   CompileTimeErrorCode.URI_WITH_INTERPOLATION,
@@ -330,6 +332,7 @@
   HintCode.FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE,
   HintCode.IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION,
   HintCode.INFERENCE_FAILURE_ON_COLLECTION_LITERAL,
+  HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE,
   HintCode.INFERENCE_FAILURE_ON_INSTANCE_CREATION,
   HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE,
   HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER,
@@ -382,8 +385,6 @@
   HintCode.SDK_VERSION_UI_AS_CODE,
   HintCode.SDK_VERSION_UI_AS_CODE_IN_CONST_CONTEXT,
   HintCode.STRICT_RAW_TYPE,
-  HintCode.STRICT_RAW_TYPE_IN_AS,
-  HintCode.STRICT_RAW_TYPE_IN_IS,
   HintCode.SUBTYPE_OF_SEALED_CLASS,
   HintCode.TYPE_CHECK_IS_NOT_NULL,
   HintCode.TYPE_CHECK_IS_NULL,
@@ -568,6 +569,7 @@
   ParserErrorCode.NON_STRING_LITERAL_AS_URI,
   ParserErrorCode.NON_USER_DEFINABLE_OPERATOR,
   ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS,
+  ParserErrorCode.NULL_AWARE_CASCADE_OUT_OF_ORDER,
   ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT,
   ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP,
   ParserErrorCode.PREFIX_AFTER_COMBINATOR,
diff --git a/pkg/analyzer/lib/src/cancelable_future.dart b/pkg/analyzer/lib/src/cancelable_future.dart
deleted file mode 100644
index ff0179b..0000000
--- a/pkg/analyzer/lib/src/cancelable_future.dart
+++ /dev/null
@@ -1,298 +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:async';
-
-/**
- * Type of callback called when the future returned by a CancelableCompleter
- * is canceled.
- */
-typedef void CancelHandler();
-
-/**
- * A way to produce [CancelableFuture] objects and to complete them later with
- * a value or error.
- *
- * This class behaves like the standard library [Completer] class, except that
- * its [future] getter returns a [CancelableFuture].
- *
- * If the future is canceled before being completed, the [CancelHandler] which
- * was passed to the constructor is invoked, and any further attempt to
- * complete the future has no effect.  For example, in the following code:
- *
- *     main() {
- *       var cc = new CancelableCompleter(() {
- *         print('cancelled'); // (2)
- *       });
- *       cc.future.then((value) {
- *         print('completed with value $value');
- *       }, onError: (error) {
- *         print('completed with error $error'); // (3)
- *       });
- *       cc.future.cancel(); // (1)
- *     }
- *
- * The call at (1) causes (2) to be invoked immediately.  (3) will be invoked
- * later (on a microtask), with an error that is an instance of
- * [FutureCanceledError].
- *
- * Note that since the closure passed to then() is executed on a microtask,
- * there is a short window of time between the call to [complete] and the
- * client being informed that the future has completed.  During this window,
- * any attempt to cancel the future will have no effect.  For example, in the
- * following code:
- *
- *     main() {
- *       var cc = new CancelableCompleter(() {
- *         print('cancelled'); // (3)
- *       });
- *       cc.future.then((value) {
- *         print('completed with value $value'); // (4)
- *       }, onError: (error) {
- *         print('completed with error $error');
- *       });
- *       cc.complete(100); // (1)
- *       cc.future.cancel(); // (2)
- *     }
- *
- * The call at (1) will place the completer in the "completed" state, so the
- * call at (2) will have no effect (in particular, (3) won't ever execute).
- * Later, (4) will be invoked on a microtask.
- */
-class CancelableCompleter<T> implements Completer<T> {
-  /**
-   * The completer which holds the state of the computation.  If the
-   * computation is canceled, this completer will remain in the non-completed
-   * state.
-   */
-  final Completer<T> _innerCompleter = new Completer<T>.sync();
-
-  /**
-   * The completer which holds the future that is exposed to the client
-   * through [future].  If the computation is canceled, this completer will
-   * be completed with a FutureCanceledError.
-   */
-  final Completer<T> _outerCompleter = new Completer<T>();
-
-  /**
-   * The callback to invoke if the 'cancel' method is called on the future
-   * returned by [future].  This callback will only be invoked if the future
-   * is canceled before being completed.
-   */
-  final CancelHandler _onCancel;
-
-  _CancelableCompleterFuture<T> _future;
-
-  /**
-   * Create a CancelableCompleter that will invoke the given callback
-   * synchronously if its future is canceled.  The callback will not be
-   * invoked if the future is completed before being canceled.
-   */
-  CancelableCompleter(this._onCancel) {
-    _future = new _CancelableCompleterFuture<T>(this);
-
-    // When the client completes the inner completer, we need to check whether
-    // the outer completer has been completed.  If it has, then the operation
-    // was canceled before it finished, and it's too late to un-cancel it, so
-    // we just ignore the result from the inner completer.  If it hasn't, then
-    // we simply pass along the result from the inner completer to the outer
-    // completer.
-    //
-    // Note that the reason it is safe for the inner completer to be
-    // synchronous is that we don't expose its future to client code, and we
-    // only use it to complete the outer completer (which is asynchronous).
-    _innerCompleter.future.then((T value) {
-      if (!_outerCompleter.isCompleted) {
-        _outerCompleter.complete(value);
-      }
-    }, onError: (Object error, StackTrace stackTrace) {
-      if (!_outerCompleter.isCompleted) {
-        _outerCompleter.completeError(error, stackTrace);
-      }
-    });
-  }
-
-  /**
-   * The [CancelableFuture] that will contain the result provided to this
-   * completer.
-   */
-  @override
-  CancelableFuture<T> get future => _future;
-
-  /**
-   * Whether the future has been completed.  This is independent of whether
-   * the future has been canceled.
-   */
-  @override
-  bool get isCompleted => _innerCompleter.isCompleted;
-
-  /**
-   * Complete [future] with the supplied value.  If the future has previously
-   * been canceled, this will have no effect on [future], however it will
-   * still set [isCompleted] to true.
-   */
-  @override
-  void complete([value]) {
-    _innerCompleter.complete(value);
-  }
-
-  /**
-   * Complete [future] with an error.  If the future has previously been
-   * canceled, this will have no effect on [future], however it will still set
-   * [isCompleted] to true.
-   */
-  @override
-  void completeError(Object error, [StackTrace stackTrace]) {
-    _innerCompleter.completeError(error, stackTrace);
-  }
-
-  void _cancel() {
-    if (!_outerCompleter.isCompleted) {
-      _outerCompleter.completeError(new FutureCanceledError());
-      _onCancel();
-    }
-  }
-}
-
-/**
- * An object representing a delayed computation that can be canceled.
- */
-abstract class CancelableFuture<T> implements Future<T> {
-  /**
-   * A CancelableFuture containing the result of calling [computation]
-   * asynchronously.  Since the computation is started without delay, calling
-   * the future's cancel method will have no effect.
-   */
-  factory CancelableFuture(computation()) =>
-      new _WrappedFuture<T>(new Future<T>(computation));
-
-  /**
-   * A CancelableFuture containing the result of calling [computation] after
-   * [duration] has passed.
-   *
-   * TODO(paulberry): if the future is canceled before the duration has
-   * elapsed, the computation should not be performed.
-   */
-  factory CancelableFuture.delayed(Duration duration, [computation()]) =>
-      new _WrappedFuture<T>(new Future<T>.delayed(duration, computation));
-
-  /**
-   * A CancelableFuture that completes with error.  Since the future is
-   * completed without delay, calling the future's cancel method will have no
-   * effect.
-   */
-  factory CancelableFuture.error(Object error, [StackTrace stackTrace]) =>
-      new _WrappedFuture<T>(new Future<T>.error(error, stackTrace));
-
-  /**
-   * A CancelableFuture containing the result of calling [computation]
-   * asynchronously with scheduleMicrotask.  Since the computation is started
-   * without delay, calling the future's cancel method will have no effect.
-   */
-  factory CancelableFuture.microtask(computation()) =>
-      new _WrappedFuture<T>(new Future<T>.microtask(computation));
-
-  /**
-   * A CancelableFuture containing the result of immediately calling
-   * [computation].  Since the computation is started without delay, calling
-   * the future's cancel method will have no effect.
-   */
-  factory CancelableFuture.sync(computation()) =>
-      new _WrappedFuture<T>(new Future<T>.sync(computation));
-
-  /**
-   * A CancelableFuture whose value is available in the next event-loop
-   * iteration.  Since the value is available without delay, calling the
-   * future's cancel method will have no effect.
-   */
-  factory CancelableFuture.value([value]) =>
-      new _WrappedFuture<T>(new Future<T>.value(value));
-
-  /**
-   * If the delayed computation has not yet completed, attempt to cancel it.
-   * Note that the cancellation is not always possible.  If the computation
-   * could be canceled, the future is completed with a FutureCanceledError.
-   * Otherwise it will behave as though cancel() was not called.
-   *
-   * Note that attempting to cancel a future that has already completed will
-   * never succeed--futures that have already completed retain their final
-   * state forever.
-   */
-  void cancel();
-}
-
-/**
- * Error which is used to complete any [CancelableFuture] which has been
- * successfully canceled by calling its 'cancel' method.
- */
-class FutureCanceledError {}
-
-class _CancelableCompleterFuture<T> implements CancelableFuture<T> {
-  final CancelableCompleter<T> _completer;
-
-  _CancelableCompleterFuture(this._completer);
-
-  @override
-  Stream<T> asStream() {
-    // TODO(paulberry): Implement this in such a way that
-    // StreamSubscription.cancel() cancels the future.
-    return _completer._outerCompleter.future.asStream();
-  }
-
-  @override
-  void cancel() {
-    _completer._cancel();
-  }
-
-  @override
-  Future<T> catchError(Function onError, {bool test(Object error)}) =>
-      _completer._outerCompleter.future.catchError(onError, test: test);
-
-  @override
-  Future<S> then<S>(FutureOr<S> onValue(T value), {Function onError}) =>
-      _completer._outerCompleter.future.then(onValue, onError: onError);
-
-  @override
-  Future<T> timeout(Duration timeLimit, {onTimeout()}) {
-    // TODO(paulberry): Implement this in such a way that a timeout cancels
-    // the future.
-    return _completer._outerCompleter.future
-        .timeout(timeLimit, onTimeout: onTimeout);
-  }
-
-  @override
-  Future<T> whenComplete(action()) =>
-      _completer._outerCompleter.future.whenComplete(action);
-}
-
-/**
- * A CancelableFuture that wraps an ordinary Future.  Attempting to cancel a
- * _WrappedFuture has no effect.
- */
-class _WrappedFuture<T> implements CancelableFuture<T> {
-  final Future<T> _future;
-
-  _WrappedFuture(this._future);
-
-  @override
-  Stream<T> asStream() => _future.asStream();
-
-  @override
-  void cancel() {}
-
-  @override
-  Future<T> catchError(Function onError, {bool test(Object error)}) =>
-      _future.catchError(onError, test: test);
-
-  @override
-  Future<S> then<S>(FutureOr<S> onValue(T value), {Function onError}) =>
-      _future.then(onValue, onError: onError);
-
-  @override
-  Future<T> timeout(Duration timeLimit, {onTimeout()}) =>
-      _future.timeout(timeLimit, onTimeout: onTimeout);
-
-  @override
-  Future<T> whenComplete(action()) => _future.whenComplete(action);
-}
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index 5b69ecb..4a58ff8 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -160,10 +160,8 @@
     InternalAnalysisContext context =
         AnalysisEngine.instance.createAnalysisContext();
     AnalysisOptionsImpl options = getAnalysisOptions(path);
-    context.contentCache = contentCache;
     context.sourceFactory = createSourceFactory(path, options);
     context.analysisOptions = options;
-    context.name = path;
     //_processAnalysisOptions(context, optionMap);
     declareVariables(context);
     return context;
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index 876243d..5e56d1f 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -2,34 +2,18 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:async';
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/cancelable_future.dart';
-import 'package:analyzer/src/context/builder.dart' show EmbedderYamlLocator;
 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';
-import 'package:analyzer/src/plugin/resolver_provider.dart';
-import 'package:analyzer/src/task/api/model.dart';
 
 /**
  * An [AnalysisContext] in which analysis can be performed.
  */
 class AnalysisContextImpl implements InternalAnalysisContext {
   /**
-   * A client-provided name used to identify this context, or `null` if the
-   * client has not provided a name.
-   */
-  @override
-  String name;
-
-  /**
    * The set of analysis options controlling the behavior of this context.
    */
   AnalysisOptionsImpl _options = new AnalysisOptionsImpl();
@@ -56,47 +40,11 @@
   TypeSystem _typeSystem;
 
   /**
-   * Determines whether this context should attempt to make use of the global
-   * SDK cache partition. Note that if this context is responsible for
-   * resynthesizing the SDK element model, this flag should be set to `false`,
-   * so that resynthesized elements belonging to this context won't leak into
-   * the global SDK cache partition.
-   */
-  bool useSdkCachePartition = true;
-
-  /**
-   * The most recently incrementally resolved source, or `null` when it was
-   * already validated, or the most recent change was not incrementally resolved.
-   */
-  Source incrementalResolutionValidation_lastUnitSource;
-
-  /**
-   * The most recently incrementally resolved library source, or `null` when it
-   * was already validated, or the most recent change was not incrementally
-   * resolved.
-   */
-  Source incrementalResolutionValidation_lastLibrarySource;
-
-  /**
-   * The result of incremental resolution result of
-   * [incrementalResolutionValidation_lastUnitSource].
-   */
-  CompilationUnit incrementalResolutionValidation_lastUnit;
-
-  @override
-  ResolverProvider fileResolverProvider;
-
-  /**
    * Initialize a newly created analysis context.
    */
   AnalysisContextImpl();
 
   @override
-  AnalysisCache get analysisCache {
-    throw UnimplementedError();
-  }
-
-  @override
   AnalysisOptions get analysisOptions => _options;
 
   @override
@@ -105,20 +53,6 @@
   }
 
   @override
-  void set analysisPriorityOrder(List<Source> sources) {
-    throw UnimplementedError();
-  }
-
-  CacheConsistencyValidator get cacheConsistencyValidator {
-    throw UnimplementedError();
-  }
-
-  @override
-  set contentCache(ContentCache value) {
-    throw UnimplementedError();
-  }
-
-  @override
   DeclaredVariables get declaredVariables => _declaredVariables;
 
   /**
@@ -128,72 +62,6 @@
     _declaredVariables = variables;
   }
 
-  @deprecated
-  @override
-  EmbedderYamlLocator get embedderYamlLocator {
-    throw UnimplementedError();
-  }
-
-  @override
-  List<AnalysisTarget> get explicitTargets {
-    throw UnimplementedError();
-  }
-
-  @override
-  List<Source> get htmlSources {
-    throw UnimplementedError();
-  }
-
-  @override
-  Stream<ImplicitAnalysisEvent> get implicitAnalysisEvents {
-    throw UnimplementedError();
-  }
-
-  @override
-  bool get isActive {
-    throw UnimplementedError();
-  }
-
-  @override
-  set isActive(bool active) {
-    throw UnimplementedError();
-  }
-
-  @override
-  bool get isDisposed {
-    throw UnimplementedError();
-  }
-
-  @override
-  List<Source> get launchableClientLibrarySources {
-    throw UnimplementedError();
-  }
-
-  @override
-  List<Source> get launchableServerLibrarySources {
-    throw UnimplementedError();
-  }
-
-  @override
-  List<Source> get librarySources {
-    throw UnimplementedError();
-  }
-
-  @override
-  List<Source> get prioritySources {
-    throw UnimplementedError();
-  }
-
-  @override
-  List<AnalysisTarget> get priorityTargets {
-    throw UnimplementedError();
-  }
-
-  @override
-  CachePartition get privateAnalysisCachePartition {
-    throw UnimplementedError();
-  }
-
   @override
   SourceFactory get sourceFactory => _sourceFactory;
 
@@ -203,25 +71,6 @@
   }
 
   @override
-  List<Source> get sources {
-    throw UnimplementedError();
-  }
-
-  /**
-   * Return a list of the sources that would be processed by
-   * [performAnalysisTask]. This method duplicates, and must therefore be kept
-   * in sync with, [getNextAnalysisTask]. This method is intended to be used for
-   * testing purposes only.
-   */
-  List<Source> get sourcesNeedingProcessing {
-    throw UnimplementedError();
-  }
-
-  List<Source> get test_priorityOrder {
-    throw UnimplementedError();
-  }
-
-  @override
   TypeProvider get typeProvider {
     return _typeProvider;
   }
@@ -240,268 +89,16 @@
   }
 
   @override
-  void addListener(AnalysisListener listener) {
-    throw UnimplementedError();
-  }
-
-  @override
-  void applyAnalysisDelta(AnalysisDelta delta) {
-    throw UnimplementedError();
-  }
-
-  @override
   void applyChanges(ChangeSet changeSet) {
     throw UnimplementedError();
   }
 
-  @override
-  String computeDocumentationComment(Element element) {
-    throw UnimplementedError();
-  }
-
-  @override
-  List<AnalysisError> computeErrors(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  List<Source> computeExportedLibraries(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  List<Source> computeImportedLibraries(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  SourceKind computeKindOf(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  LibraryElement computeLibraryElement(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  LineInfo computeLineInfo(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  CancelableFuture<CompilationUnit> computeResolvedCompilationUnitAsync(
-      Source unitSource, Source librarySource) {
-    throw UnimplementedError();
-  }
-
   /**
    * Create an analysis cache based on the given source [factory].
    */
   AnalysisCache createCacheFromSourceFactory(SourceFactory factory) {
     throw UnimplementedError();
   }
-
-  @override
-  void dispose() {}
-
-  @override
-  List<CompilationUnit> ensureResolvedDartUnits(Source unitSource) {
-    throw UnimplementedError();
-  }
-
-  @override
-  bool exists(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  CompilationUnitElement getCompilationUnitElement(
-      Source unitSource, Source librarySource) {
-    throw UnimplementedError();
-  }
-
-  @override
-  TimestampedData<String> getContents(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  InternalAnalysisContext getContextFor(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  Element getElement(ElementLocation location) {
-    throw UnimplementedError();
-  }
-
-  @override
-  AnalysisErrorInfo getErrors(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  List<Source> getHtmlFilesReferencing(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  SourceKind getKindOf(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  List<Source> getLibrariesContaining(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  List<Source> getLibrariesDependingOn(Source librarySource) {
-    throw UnimplementedError();
-  }
-
-  @override
-  List<Source> getLibrariesReferencedFromHtml(Source htmlSource) {
-    throw UnimplementedError();
-  }
-
-  @override
-  LibraryElement getLibraryElement(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  LineInfo getLineInfo(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  int getModificationStamp(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  ChangeNoticeImpl getNotice(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  Namespace getPublicNamespace(LibraryElement library) {
-    // TODO(brianwilkerson) Rename this to not start with 'get'.
-    // Note that this is not part of the API of the interface.
-    // TODO(brianwilkerson) The public namespace used to be cached, but no
-    // longer is. Konstantin adds:
-    // The only client of this method is NamespaceBuilder._createExportMapping(),
-    // and it is not used with tasks - instead we compute export namespace once
-    // using BuildExportNamespaceTask and reuse in scopes.
-    NamespaceBuilder builder = new NamespaceBuilder();
-    return builder.createPublicNamespaceForLibrary(library);
-  }
-
-  @override
-  CompilationUnit getResolvedCompilationUnit(
-      Source unitSource, LibraryElement library) {
-    throw UnimplementedError();
-  }
-
-  @override
-  CompilationUnit getResolvedCompilationUnit2(
-      Source unitSource, Source librarySource) {
-    throw UnimplementedError();
-  }
-
-  @override
-  List<Source> getSourcesWithFullName(String path) {
-    throw UnimplementedError();
-  }
-
-  @override
-  bool handleContentsChanged(
-      Source source, String originalContents, String newContents, bool notify) {
-    throw UnimplementedError();
-  }
-
-  /**
-   * Invalidate analysis cache and notify work managers that they have work
-   * to do.
-   */
-  void invalidateCachedResults() {
-    throw UnimplementedError();
-  }
-
-  @override
-  void invalidateLibraryHints(Source librarySource) {
-    throw UnimplementedError();
-  }
-
-  @override
-  bool isClientLibrary(Source librarySource) {
-    throw UnimplementedError();
-  }
-
-  @override
-  bool isServerLibrary(Source librarySource) {
-    throw UnimplementedError();
-  }
-
-  @override
-  CompilationUnit parseCompilationUnit(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  AnalysisResult performAnalysisTask() {
-    throw UnimplementedError();
-  }
-
-  @override
-  void recordLibraryElements(Map<Source, LibraryElement> elementMap) {
-    throw UnimplementedError();
-  }
-
-  @override
-  void removeListener(AnalysisListener listener) {
-    throw UnimplementedError();
-  }
-
-  @override
-  CompilationUnit resolveCompilationUnit(
-      Source unitSource, LibraryElement library) {
-    throw UnimplementedError();
-  }
-
-  @override
-  CompilationUnit resolveCompilationUnit2(
-      Source unitSource, Source librarySource) {
-    throw UnimplementedError();
-  }
-
-  @override
-  void setChangedContents(Source source, String contents, int offset,
-      int oldLength, int newLength) {
-    throw UnimplementedError();
-  }
-
-  @override
-  void setContents(Source source, String contents) {
-    throw UnimplementedError();
-  }
-
-  @override
-  bool shouldErrorsBeAnalyzed(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  void test_flushAstStructures(Source source) {
-    throw UnimplementedError();
-  }
-
-  @override
-  void visitContentCache(ContentCacheVisitor visitor) {
-    throw UnimplementedError();
-  }
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
index 0132454..06b9e65 100644
--- a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
@@ -16,6 +16,7 @@
   EnableString.set_literals: ExperimentalFeatures.set_literals,
   EnableString.spread_collections: ExperimentalFeatures.spread_collections,
   EnableString.triple_shift: ExperimentalFeatures.triple_shift,
+  EnableString.variance: ExperimentalFeatures.variance,
 
   // ignore: deprecated_member_use_from_same_package
   EnableString.bogus_disabled: ExperimentalFeatures.bogus_disabled,
@@ -31,6 +32,7 @@
       true, // set-literals
       true, // spread-collections
       IsEnabledByDefault.triple_shift,
+      IsEnabledByDefault.variance,
       false, // bogus-disabled
       true, // bogus-enabled
     ];
@@ -59,6 +61,9 @@
   /// String to enable the experiment "triple-shift"
   static const String triple_shift = 'triple-shift';
 
+  /// String to enable the experiment "variance"
+  static const String variance = 'variance';
+
   /// String to enable the experiment "bogus-disabled"
   @deprecated
   static const String bogus_disabled = 'bogus-disabled';
@@ -122,9 +127,12 @@
       IsExpired.triple_shift,
       'Triple-shift operator');
 
+  static const variance = const ExperimentalFeature(7, EnableString.variance,
+      IsEnabledByDefault.variance, IsExpired.variance, 'Sound variance.');
+
   @deprecated
   static const bogus_disabled = const ExperimentalFeature(
-      7,
+      8,
       // ignore: deprecated_member_use_from_same_package
       EnableString.bogus_disabled,
       IsEnabledByDefault.bogus_disabled,
@@ -133,7 +141,7 @@
 
   @deprecated
   static const bogus_enabled = const ExperimentalFeature(
-      8,
+      9,
       // ignore: deprecated_member_use_from_same_package
       EnableString.bogus_enabled,
       IsEnabledByDefault.bogus_enabled,
@@ -166,6 +174,9 @@
   /// Default state of the experiment "triple-shift"
   static const bool triple_shift = false;
 
+  /// Default state of the experiment "variance"
+  static const bool variance = false;
+
   /// Default state of the experiment "bogus-disabled"
   @deprecated
   static const bool bogus_disabled = false;
@@ -200,6 +211,9 @@
   /// Expiration status of the experiment "triple-shift"
   static const bool triple_shift = false;
 
+  /// Expiration status of the experiment "variance"
+  static const bool variance = false;
+
   /// Expiration status of the experiment "bogus-disabled"
   static const bool bogus_disabled = true;
 
@@ -241,5 +255,8 @@
   /// Current state for the flag "triple-shift"
   bool get triple_shift => isEnabled(ExperimentalFeatures.triple_shift);
 
+  /// Current state for the flag "variance"
+  bool get variance => isEnabled(ExperimentalFeatures.variance);
+
   bool isEnabled(covariant ExperimentalFeature feature);
 }
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index a8c8650..013e122 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -7,6 +7,7 @@
 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/nullability_suffix.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/file_system/file_system.dart';
@@ -22,7 +23,6 @@
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/handle.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
-import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/resolver/ast_rewrite.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
@@ -658,8 +658,6 @@
         source, _typeProvider, errorListener,
         nameScope: _libraryScope));
 
-    // TODO(scheglov) remove EnumMemberBuilder class
-
     new TypeParameterBoundsResolver(_context.typeSystem, _libraryElement,
             source, errorListener, unit.featureSet)
         .resolveTypeBounds(unit);
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index 2857311..f090722 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -219,6 +219,7 @@
     return _typeSystem ??= Dart2TypeSystem(
       typeProvider,
       implicitCasts: analysisOptions.implicitCasts,
+      strictInference: analysisOptions.strictInference,
     );
   }
 
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 0d75a23..9dd4e72 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -5991,6 +5991,10 @@
   bool get isCascaded => period != null;
 
   @override
+  bool get isNullAware =>
+      leftBracket.type == TokenType.QUESTION_PERIOD_OPEN_SQUARE_BRACKET;
+
+  @override
   Precedence get precedence => Precedence.postfix;
 
   @deprecated
@@ -7185,6 +7189,9 @@
           operator.type == TokenType.QUESTION_PERIOD_PERIOD);
 
   @override
+  bool get isNullAware => operator?.type == TokenType.QUESTION_PERIOD;
+
+  @override
   SimpleIdentifier get methodName => _methodName;
 
   @override
@@ -8444,6 +8451,10 @@
           operator.type == TokenType.QUESTION_PERIOD_PERIOD);
 
   @override
+  bool get isNullAware =>
+      operator != null && operator.type == TokenType.QUESTION_PERIOD;
+
+  @override
   Precedence get precedence => Precedence.postfix;
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index 3c2efbf..9f37e6b 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -279,8 +279,12 @@
         assert(!node.isConst);
         return;
       }
-      _reportErrors(result.errors,
-          CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE);
+      if (node.isConst) {
+        _reportErrors(result.errors,
+            CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE);
+      } else {
+        _reportErrors(result.errors, null);
+      }
       _reportErrorIfFromDeferredLibrary(
           initializer,
           CompileTimeErrorCode
@@ -352,7 +356,7 @@
       MethodElement method =
           element.lookUpConcreteMethod("==", _currentLibrary);
       if (method == null ||
-          (method.enclosingElement as ClassElement).type.isObject) {
+          (method.enclosingElement as ClassElement).isDartCoreObject) {
         return false;
       }
       // there is == that we don't like
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index dd26599..c8395a2 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/dart/ast/visitor.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/error/error.dart';
 import 'package:analyzer/error/listener.dart';
@@ -831,7 +832,7 @@
     if (!constructor.isFactory) {
       return null;
     }
-    if (constructor.enclosingElement.type == typeProvider.symbolType) {
+    if (constructor.enclosingElement == typeProvider.symbolElement) {
       // The dart:core.Symbol has a const factory constructor that redirects
       // to dart:_internal.Symbol.  That in turn redirects to an external
       // const constructor, which we won't be able to evaluate.
@@ -1256,7 +1257,7 @@
         nodeType is InterfaceType && nodeType.typeArguments.isNotEmpty
             ? nodeType.typeArguments[0]
             : _typeProvider.dynamicType;
-    InterfaceType listType = _typeProvider.listType.instantiate([elementType]);
+    InterfaceType listType = _typeProvider.listType2(elementType);
     return new DartObjectImpl(listType, new ListState(list));
   }
 
@@ -1390,8 +1391,7 @@
           valueType = typeArguments[1];
         }
       }
-      InterfaceType mapType =
-          _typeProvider.mapType.instantiate([keyType, valueType]);
+      InterfaceType mapType = _typeProvider.mapType2(keyType, valueType);
       return new DartObjectImpl(mapType, new MapState(map));
     } else {
       if (!node.isConst) {
@@ -1412,7 +1412,7 @@
           nodeType is InterfaceType && nodeType.typeArguments.isNotEmpty
               ? nodeType.typeArguments[0]
               : _typeProvider.dynamicType;
-      InterfaceType setType = _typeProvider.setType.instantiate([elementType]);
+      InterfaceType setType = _typeProvider.setType2(elementType);
       return new DartObjectImpl(setType, new SetState(set));
     }
   }
@@ -1640,13 +1640,36 @@
         }
         return new DartObjectImpl(functionType, new FunctionState(function));
       }
-    } else if (variableElement is TypeDefiningElement) {
+    } else if (variableElement is ClassElement) {
+      var type = variableElement.instantiate(
+        typeArguments: variableElement.typeParameters
+            .map((t) => _typeProvider.dynamicType)
+            .toList(),
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
+      return DartObjectImpl(_typeProvider.typeType, TypeState(type));
+    } else if (variableElement is DynamicElementImpl) {
+      return DartObjectImpl(
+        _typeProvider.typeType,
+        TypeState(_typeProvider.dynamicType),
+      );
+    } else if (variableElement is FunctionTypeAliasElement) {
+      var type = variableElement.instantiate2(
+        typeArguments: variableElement.typeParameters
+            .map((t) => _typeProvider.dynamicType)
+            .toList(),
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
+      return DartObjectImpl(_typeProvider.typeType, TypeState(type));
+    } else if (variableElement is NeverElementImpl) {
+      return DartObjectImpl(
+        _typeProvider.typeType,
+        TypeState(_typeProvider.neverType),
+      );
+    } else if (variableElement is TypeParameterElement) {
       // Constants may not refer to type parameters.
-      if (variableElement is! TypeParameterElement) {
-        return new DartObjectImpl(
-            _typeProvider.typeType, new TypeState(variableElement.type));
-      }
     }
+
     // TODO(brianwilkerson) Figure out which error to report.
     _error(node, null);
     return null;
diff --git a/pkg/analyzer/lib/src/dart/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart
index b6c9ab4..4565244 100644
--- a/pkg/analyzer/lib/src/dart/element/builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/builder.dart
@@ -166,7 +166,7 @@
     _setCodeRange(enumElement, node);
     enumElement.metadata = _createElementAnnotations(node.metadata);
     setElementDocumentationComment(enumElement, node);
-    InterfaceTypeImpl enumType = enumElement.type;
+    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
@@ -368,7 +368,6 @@
       ..parameters = parameters;
     element.typeParameters = typeParameters;
     _createTypeParameterTypes(typeParameters);
-    element.type = new FunctionTypeImpl.forTypedef(element);
     _currentHolder.addTypeAlias(element);
     aliasName.staticElement = element;
     holder.validate();
@@ -387,7 +386,6 @@
     setElementDocumentationComment(element, node);
     element.typeParameters = typeParameters;
     _createTypeParameterTypes(typeParameters);
-    element.type = new FunctionTypeImpl.forTypedef(element);
     element.function = node.functionType?.type?.element;
     _currentHolder.addTypeAlias(element);
     aliasName.staticElement = element;
@@ -728,10 +726,7 @@
     for (int i = 0; i < typeParameterCount; i++) {
       TypeParameterElementImpl typeParameter =
           typeParameters[i] as TypeParameterElementImpl;
-      TypeParameterTypeImpl typeParameterType =
-          new TypeParameterTypeImpl(typeParameter);
-      typeParameter.type = typeParameterType;
-      typeArguments[i] = typeParameterType;
+      typeArguments[i] = TypeParameterTypeImpl(typeParameter);
     }
     return typeArguments;
   }
@@ -1557,9 +1552,6 @@
         new TypeParameterElementImpl.forNode(parameterName);
     _setCodeRange(typeParameter, node);
     typeParameter.metadata = _createElementAnnotations(node.metadata);
-    TypeParameterTypeImpl typeParameterType =
-        new TypeParameterTypeImpl(typeParameter);
-    typeParameter.type = typeParameterType;
     _currentHolder.addTypeParameter(typeParameter);
     parameterName.staticElement = typeParameter;
     super.visitTypeParameter(node);
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 59e5cff..98921f2 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/dart/ast/token.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/error/error.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
@@ -34,6 +35,7 @@
 import 'package:analyzer/src/summary2/linked_unit_context.dart';
 import 'package:analyzer/src/summary2/reference.dart';
 import 'package:analyzer/src/util/comment.dart';
+import 'package:meta/meta.dart';
 
 /// Assert that the given [object] is null, which in the places where this
 /// function is called means that the element is not resynthesized.
@@ -48,6 +50,9 @@
 /// A concrete implementation of a [ClassElement].
 abstract class AbstractClassElementImpl extends ElementImpl
     implements ClassElement {
+  /// The type defined by the class.
+  InterfaceType _thisType;
+
   /// A list containing all of the accessors (getters and setters) contained in
   /// this class.
   List<PropertyAccessorElement> _accessors;
@@ -102,6 +107,9 @@
   }
 
   @override
+  bool get isDartCoreObject => false;
+
+  @override
   bool get isEnum => false;
 
   @override
@@ -114,6 +122,29 @@
   List<InterfaceType> get superclassConstraints => const <InterfaceType>[];
 
   @override
+  InterfaceType get thisType {
+    if (_thisType == null) {
+      // TODO(scheglov) `library` is null in low-level unit tests
+      var nullabilitySuffix = library?.isNonNullableByDefault == true
+          ? NullabilitySuffix.none
+          : NullabilitySuffix.star;
+      List<DartType> typeArguments;
+      if (typeParameters.isNotEmpty) {
+        typeArguments = typeParameters.map<DartType>((t) {
+          return t.instantiate(nullabilitySuffix: nullabilitySuffix);
+        }).toList();
+      } else {
+        typeArguments = const <DartType>[];
+      }
+      return _thisType = instantiate(
+        typeArguments: typeArguments,
+        nullabilitySuffix: nullabilitySuffix,
+      );
+    }
+    return _thisType;
+  }
+
+  @override
   T accept<T>(ElementVisitor<T> visitor) => visitor.visitClassElement(this);
 
   @deprecated
@@ -189,6 +220,23 @@
   }
 
   @override
+  InterfaceType instantiate({
+    @required List<DartType> typeArguments,
+    @required NullabilitySuffix nullabilitySuffix,
+  }) {
+    if (typeArguments.length != typeParameters.length) {
+      var ta = 'typeArguments.length (${typeArguments.length})';
+      var tp = 'typeParameters.length (${typeParameters.length})';
+      throw ArgumentError('$ta != $tp');
+    }
+    return InterfaceTypeImpl.explicit(
+      this,
+      typeArguments,
+      nullabilitySuffix: nullabilitySuffix,
+    );
+  }
+
+  @override
   MethodElement lookUpConcreteMethod(
           String methodName, LibraryElement library) =>
       _first(getImplementationsOfMethod(this, methodName).where(
@@ -511,7 +559,7 @@
   @override
   List<InterfaceType> get allSupertypes {
     List<InterfaceType> list = new List<InterfaceType>();
-    collectAllSupertypes(list, type, type);
+    collectAllSupertypes(list, thisType, thisType);
     return list;
   }
 
@@ -728,7 +776,7 @@
     MethodElement method = lookUpConcreteMethod(
         FunctionElement.NO_SUCH_METHOD_METHOD_NAME, library);
     ClassElement definingClass = method?.enclosingElement;
-    return definingClass != null && !definingClass.type.isObject;
+    return definingClass != null && !definingClass.isDartCoreObject;
   }
 
   @override
@@ -826,6 +874,9 @@
   }
 
   @override
+  bool get isDartCoreObject => !isMixin && supertype == null;
+
+  @override
   bool get isMixinApplication {
     if (linkedNode != null) {
       return linkedNode is ClassTypeAlias;
@@ -1897,7 +1948,7 @@
   }
 
   @override
-  String get identifier => source.encoding;
+  String get identifier => '${source.uri}';
 
   @override
   ElementKind get kind => ElementKind.COMPILATION_UNIT;
@@ -2392,7 +2443,7 @@
   }
 
   @override
-  InterfaceType get type => _enum.type;
+  InterfaceType get type => _enum.thisType;
 }
 
 /// The synthetic `values` field of an enum.
@@ -2423,8 +2474,7 @@
   @override
   InterfaceType get type {
     if (_type == null) {
-      InterfaceType listType = context.typeProvider.listType;
-      return _type = listType.instantiate(<DartType>[_enum.type]);
+      return _type = context.typeProvider.listType2(_enum.thisType);
     }
     return _type;
   }
@@ -2744,7 +2794,7 @@
   }
 
   @override
-  DartType get returnType => enclosingElement.type;
+  DartType get returnType => enclosingElement.thisType;
 
   void set returnType(DartType returnType) {
     assert(false);
@@ -3006,9 +3056,6 @@
   static DynamicElementImpl get instance =>
       DynamicTypeImpl.instance.element as DynamicElementImpl;
 
-  @override
-  DynamicTypeImpl type;
-
   /// Initialize a newly created instance of this class. Instances of this class
   /// should <b>not</b> be created except as part of creating the type
   /// associated with this element. The single instance of this class should be
@@ -3021,6 +3068,9 @@
   ElementKind get kind => ElementKind.DYNAMIC;
 
   @override
+  DartType get type => DynamicTypeImpl.instance;
+
+  @override
   T accept<T>(ElementVisitor<T> visitor) => null;
 }
 
@@ -3709,7 +3759,9 @@
 
   @deprecated
   @override
-  CompilationUnit get unit => context.resolveCompilationUnit(source, library);
+  CompilationUnit get unit {
+    throw UnimplementedError();
+  }
 
   @override
   bool operator ==(Object object) {
@@ -6379,6 +6431,18 @@
   }
 
   @override
+  FunctionType instantiate2({
+    @required List<DartType> typeArguments,
+    @required NullabilitySuffix nullabilitySuffix,
+  }) {
+    // TODO(scheglov) Replace with strict function type.
+    return FunctionTypeImpl.forTypedef(
+      this,
+      nullabilitySuffix: nullabilitySuffix,
+    ).instantiate(typeArguments);
+  }
+
+  @override
   void visitChildren(ElementVisitor visitor) {
     super.visitChildren(visitor);
     safelyVisitChildren(typeParameters, visitor);
@@ -6412,7 +6476,7 @@
 
     if (typeArguments == null ||
         parameterElements.length != typeArguments.length) {
-      DartType dynamicType = DynamicElementImpl.instance.type;
+      DartType dynamicType = element.context.typeProvider.dynamicType;
       typeArguments = new List<DartType>.filled(parameterCount, dynamicType);
     }
 
@@ -7182,7 +7246,7 @@
   }
 
   @override
-  String get identifier => _definingCompilationUnit.source.encoding;
+  String get identifier => '${_definingCompilationUnit.source.uri}';
 
   @override
   List<LibraryElement> get importedLibraries {
@@ -8368,9 +8432,6 @@
   static NeverElementImpl get instance =>
       BottomTypeImpl.instance.element as NeverElementImpl;
 
-  @override
-  BottomTypeImpl type;
-
   /// Initialize a newly created instance of this class. Instances of this class
   /// should <b>not</b> be created except as part of creating the type
   /// associated with this element. The single instance of this class should be
@@ -8383,7 +8444,26 @@
   ElementKind get kind => ElementKind.NEVER;
 
   @override
+  DartType get type {
+    throw StateError('Should not be accessed.');
+  }
+
+  @override
   T accept<T>(ElementVisitor<T> visitor) => null;
+
+  DartType instantiate({
+    @required NullabilitySuffix nullabilitySuffix,
+  }) {
+    switch (nullabilitySuffix) {
+      case NullabilitySuffix.question:
+        return BottomTypeImpl.instanceNullable;
+      case NullabilitySuffix.star:
+        return BottomTypeImpl.instanceLegacy;
+      case NullabilitySuffix.none:
+        return BottomTypeImpl.instance;
+    }
+    throw StateError('Unsupported nullability: $nullabilitySuffix');
+  }
 }
 
 /// A [VariableElementImpl], which is not a parameter.
@@ -10158,6 +10238,13 @@
       buffer.write(bound);
     }
   }
+
+  @override
+  TypeParameterType instantiate({
+    @required NullabilitySuffix nullabilitySuffix,
+  }) {
+    return TypeParameterTypeImpl(this, nullabilitySuffix: nullabilitySuffix);
+  }
 }
 
 /// Mixin representing an element which can have type parameters.
@@ -10222,7 +10309,8 @@
   /// element's type parameters.
   List<TypeParameterType> get typeParameterTypes {
     return _typeParameterTypes ??= typeParameters
-        .map((TypeParameterElement e) => e.type)
+        .map((TypeParameterElement e) =>
+            e.instantiate(nullabilitySuffix: NullabilitySuffix.star))
         .toList(growable: false);
   }
 
diff --git a/pkg/analyzer/lib/src/dart/element/handle.dart b/pkg/analyzer/lib/src/dart/element/handle.dart
index e13d565..534b44f 100644
--- a/pkg/analyzer/lib/src/dart/element/handle.dart
+++ b/pkg/analyzer/lib/src/dart/element/handle.dart
@@ -6,6 +6,7 @@
 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';
@@ -13,6 +14,7 @@
 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].
@@ -70,6 +72,9 @@
   bool get isAbstract => actualElement.isAbstract;
 
   @override
+  bool get isDartCoreObject => actualElement.isDartCoreObject;
+
+  @override
   bool get isEnum => actualElement.isEnum;
 
   @override
@@ -113,6 +118,9 @@
   InterfaceType get supertype => actualElement.supertype;
 
   @override
+  InterfaceType get thisType => actualElement.thisType;
+
+  @override
   InterfaceType get type => actualElement.type;
 
   @override
@@ -145,6 +153,17 @@
       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);
@@ -763,6 +782,17 @@
   @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,
+    );
+  }
 }
 
 /**
@@ -810,6 +840,17 @@
   @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,
+    );
+  }
 }
 
 /**
@@ -1234,6 +1275,13 @@
 
   @override
   TypeParameterType get type => actualElement.type;
+
+  @override
+  TypeParameterType instantiate({
+    @required NullabilitySuffix nullabilitySuffix,
+  }) {
+    return actualElement.instantiate(nullabilitySuffix: nullabilitySuffix);
+  }
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index fda6a4d..fc66691 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -6,6 +6,7 @@
 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/dart/element/type.dart';
@@ -14,6 +15,7 @@
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:meta/meta.dart';
 
 /**
  * A constructor element defined in a parameterized type where the values of the
@@ -55,7 +57,7 @@
 
   @override
   ConstructorElement get redirectedConstructor {
-    var definingType = _substitution.substituteType(enclosingElement.type);
+    var definingType = _substitution.substituteType(enclosingElement.thisType);
     return from(baseElement.redirectedConstructor, definingType);
   }
 
@@ -251,6 +253,10 @@
   @override
   FieldElement get field {
     var field = (baseElement as FieldFormalParameterElement).field;
+    if (field == null) {
+      return null;
+    }
+
     return FieldMember(field, _substitution);
   }
 
@@ -932,6 +938,13 @@
   }
 
   @override
+  TypeParameterType instantiate({
+    @required NullabilitySuffix nullabilitySuffix,
+  }) {
+    return baseElement.instantiate(nullabilitySuffix: nullabilitySuffix);
+  }
+
+  @override
   String toString() {
     var buffer = StringBuffer();
     appendTo(buffer);
@@ -958,6 +971,10 @@
     List<TypeParameterElement> formals,
     MapSubstitution substitution,
   ) {
+    if (substitution.map.isEmpty) {
+      return formals;
+    }
+
     // Create type formals with specialized bounds.
     // For example `<U extends T>` where T comes from an outer scope.
     var newElements = formals.toList(growable: false);
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 3c1e839..ca2c1e5 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -6,6 +6,7 @@
 
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart';
@@ -92,11 +93,7 @@
    * Prevent the creation of instances of this class.
    */
   BottomTypeImpl._(this.nullabilitySuffix)
-      : super(new NeverElementImpl(), "Never") {
-    if (nullabilitySuffix == NullabilitySuffix.none) {
-      (element as NeverElementImpl).type = this;
-    }
-  }
+      : super(new NeverElementImpl(), "Never");
 
   @override
   int get hashCode => 0;
@@ -393,10 +390,7 @@
   /**
    * Prevent the creation of instances of this class.
    */
-  DynamicTypeImpl._()
-      : super(new DynamicElementImpl(), Keyword.DYNAMIC.lexeme) {
-    (element as DynamicElementImpl).type = this;
-  }
+  DynamicTypeImpl._() : super(new DynamicElementImpl(), Keyword.DYNAMIC.lexeme);
 
   /**
    * Constructor used by [CircularTypeImpl].
@@ -529,7 +523,6 @@
       var freshElement =
           new TypeParameterElementImpl.synthetic(typeParamElement.name);
       var freshTypeVar = new TypeParameterTypeImpl(freshElement);
-      freshElement.type = freshTypeVar;
 
       typeVars.add(typeParamElement.type);
       freshTypeVars.add(freshTypeVar);
@@ -1407,20 +1400,7 @@
 
   @override
   List<InterfaceType> get interfaces {
-    ClassElement classElement = element;
-    List<InterfaceType> interfaces = classElement.interfaces;
-    List<TypeParameterElement> typeParameters = classElement.typeParameters;
-    List<DartType> parameterTypes = classElement.type.typeArguments;
-    if (typeParameters.isEmpty) {
-      return interfaces;
-    }
-    int count = interfaces.length;
-    List<InterfaceType> typedInterfaces = new List<InterfaceType>(count);
-    for (int i = 0; i < count; i++) {
-      typedInterfaces[i] =
-          interfaces[i].substitute2(typeArguments, parameterTypes);
-    }
-    return typedInterfaces;
+    return _instantiateSuperTypes(element.interfaces);
   }
 
   @override
@@ -1574,17 +1554,12 @@
 
   @override
   InterfaceType get superclass {
-    ClassElement classElement = element;
-    InterfaceType supertype = classElement.supertype;
+    InterfaceType supertype = element.supertype;
     if (supertype == null) {
       return null;
     }
-    List<DartType> typeParameters = classElement.type.typeArguments;
-    if (typeArguments.isEmpty ||
-        typeArguments.length != typeParameters.length) {
-      return supertype;
-    }
-    return supertype.substitute2(typeArguments, typeParameters);
+
+    return Substitution.fromInterfaceType(this).substituteType(supertype);
   }
 
   @override
@@ -2341,17 +2316,17 @@
   }
 
   List<InterfaceType> _instantiateSuperTypes(List<InterfaceType> defined) {
-    List<TypeParameterElement> typeParameters = element.typeParameters;
-    if (typeParameters.isEmpty) {
-      return defined;
+    if (defined.isEmpty) return defined;
+
+    var typeParameters = element.typeParameters;
+    if (typeParameters.isEmpty) return defined;
+
+    var substitution = Substitution.fromInterfaceType(this);
+    var result = List<InterfaceType>(defined.length);
+    for (int i = 0; i < defined.length; i++) {
+      result[i] = substitution.substituteType(defined[i]);
     }
-    List<DartType> instantiated = element.type.typeArguments;
-    int count = defined.length;
-    List<InterfaceType> typedConstraints = new List<InterfaceType>(count);
-    for (int i = 0; i < count; i++) {
-      typedConstraints[i] = defined[i].substitute2(typeArguments, instantiated);
-    }
-    return typedConstraints;
+    return result;
   }
 
   /**
@@ -2579,38 +2554,6 @@
 }
 
 /**
- * Suffix indicating the nullability of a type.
- *
- * This enum describes whether a `?` or `*` would be used at the end of the
- * canonical representation of a type.  It's subtly different the notions of
- * "nullable", "non-nullable", "potentially nullable", and "potentially
- * non-nullable" defined by the spec.  For example, the type `Null` is nullable,
- * even though it lacks a trailing `?`.
- */
-enum NullabilitySuffix {
-  /**
-   * An indication that the canonical representation of the type under
-   * consideration ends with `?`.  Types having this nullability suffix should
-   * be interpreted as being unioned with the Null type.
-   */
-  question,
-
-  /**
-   * An indication that the canonical representation of the type under
-   * consideration ends with `*`.  Types having this nullability suffix are
-   * called "legacy types"; it has not yet been determined whether they should
-   * be unioned with the Null type.
-   */
-  star,
-
-  /**
-   * An indication that the canonical representation of the type under
-   * consideration does not end with either `?` or `*`.
-   */
-  none
-}
-
-/**
  * The abstract class `TypeImpl` implements the behavior common to objects
  * representing the declared type of elements in the element model.
  */
@@ -3675,7 +3618,6 @@
       if (identical(bound, newBound)) return p;
       var element = new TypeParameterElementImpl.synthetic(p.name);
       element.bound = newBound;
-      element.type = new TypeParameterTypeImpl(element);
       return element;
     }
 
diff --git a/pkg/analyzer/lib/src/dart/element/type_algebra.dart b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
index f3e234d..bc9e976 100644
--- a/pkg/analyzer/lib/src/dart/element/type_algebra.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
@@ -201,6 +201,34 @@
     return freshElement;
   }
 
+  @override
+  List<TypeParameterElement> freshTypeParameters(
+      List<TypeParameterElement> elements) {
+    if (elements.isEmpty) {
+      return const <TypeParameterElement>[];
+    }
+
+    var freshElements = List<TypeParameterElement>(elements.length);
+    for (var i = 0; i < elements.length; i++) {
+      var element = elements[i];
+      var freshElement = TypeParameterElementImpl(element.name, -1);
+      freshElements[i] = freshElement;
+      var freshType = TypeParameterTypeImpl(freshElement);
+      freshElement.type = freshType;
+      substitution[element] = freshType;
+    }
+
+    for (var i = 0; i < freshElements.length; i++) {
+      var element = elements[i];
+      if (element.bound != null) {
+        TypeParameterElementImpl freshElement = freshElements[i];
+        freshElement.bound = visit(element.bound);
+      }
+    }
+
+    return freshElements;
+  }
+
   DartType lookup(TypeParameterElement parameter, bool upperBound) {
     return substitution[parameter];
   }
@@ -247,8 +275,8 @@
     }
   }
 
-  @override
-  TypeParameterElement freshTypeParameter(TypeParameterElement element) {
+  List<TypeParameterElement> freshTypeParameters(
+      List<TypeParameterElement> parameters) {
     throw 'Create a fresh environment first';
   }
 
@@ -283,15 +311,8 @@
     target.useCounter++;
   }
 
-  TypeParameterElement freshTypeParameter(TypeParameterElement element);
-
   List<TypeParameterElement> freshTypeParameters(
-      List<TypeParameterElement> parameters) {
-    if (parameters.isEmpty) {
-      return const <TypeParameterElement>[];
-    }
-    return parameters.map(freshTypeParameter).toList();
-  }
+      List<TypeParameterElement> elements);
 
   DartType getSubstitute(TypeParameterElement parameter) {
     var environment = this;
@@ -339,14 +360,18 @@
     // any uses, but does not tell if the resulting function type is distinct.
     // Our own use counter will get incremented if something from our
     // environment has been used inside the function.
-    var inner = type.typeFormals.isEmpty ? this : newInnerEnvironment();
     int before = this.useCounter;
 
+    var inner = this;
+    var typeFormals = type.typeFormals;
+    if (typeFormals.isNotEmpty) {
+      inner = newInnerEnvironment();
+      typeFormals = inner.freshTypeParameters(typeFormals);
+    }
+
     // Invert the variance when translating parameters.
     inner.invertVariance();
 
-    var typeFormals = inner.freshTypeParameters(type.typeFormals);
-
     var parameters = type.parameters.map((parameter) {
       var type = inner.visit(parameter.type);
       return _parameterElement(parameter, type);
@@ -376,14 +401,18 @@
     // any uses, but does not tell if the resulting function type is distinct.
     // Our own use counter will get incremented if something from our
     // environment has been used inside the function.
-    var inner = type.typeFormals.isEmpty ? this : newInnerEnvironment();
     int before = this.useCounter;
 
+    var inner = this;
+    var typeFormals = type.typeFormals;
+    if (typeFormals.isNotEmpty) {
+      inner = newInnerEnvironment();
+      typeFormals = inner.freshTypeParameters(typeFormals);
+    }
+
     // Invert the variance when translating parameters.
     inner.invertVariance();
 
-    var typeFormals = inner.freshTypeParameters(type.typeFormals);
-
     var parameters = type.parameters.map((parameter) {
       var type = inner.visit(parameter.type);
       return _parameterElement(parameter, type);
diff --git a/pkg/analyzer/lib/src/dart/element/type_provider.dart b/pkg/analyzer/lib/src/dart/element/type_provider.dart
index 0f4a101..952e495 100644
--- a/pkg/analyzer/lib/src/dart/element/type_provider.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_provider.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/constant/value.dart';
 import 'package:analyzer/src/dart/element/type.dart';
@@ -44,6 +45,15 @@
   final LibraryElement _coreLibrary;
   final LibraryElement _asyncLibrary;
 
+  ClassElement _futureElement;
+  ClassElement _futureOrElement;
+  ClassElement _iterableElement;
+  ClassElement _listElement;
+  ClassElement _mapElement;
+  ClassElement _setElement;
+  ClassElement _streamElement;
+  ClassElement _symbolElement;
+
   InterfaceType _boolType;
   InterfaceType _deprecatedType;
   InterfaceType _doubleType;
@@ -119,19 +129,39 @@
 
   @override
   InterfaceType get futureDynamicType {
-    _futureDynamicType ??= futureType.instantiate(<DartType>[dynamicType]);
+    _futureDynamicType ??= InterfaceTypeImpl.explicit(
+      futureElement,
+      [dynamicType],
+      nullabilitySuffix: _nullabilitySuffix,
+    );
     return _futureDynamicType;
   }
 
+  ClassElement get futureElement {
+    return _futureElement ??= _getClassElement(_asyncLibrary, 'Future');
+  }
+
   @override
   InterfaceType get futureNullType {
-    _futureNullType ??= futureType.instantiate(<DartType>[nullType]);
+    _futureNullType ??= InterfaceTypeImpl.explicit(
+      futureElement,
+      [nullType],
+      nullabilitySuffix: _nullabilitySuffix,
+    );
     return _futureNullType;
   }
 
+  ClassElement get futureOrElement {
+    return _futureOrElement ??= _getClassElement(_asyncLibrary, 'FutureOr');
+  }
+
   @override
   InterfaceType get futureOrNullType {
-    _futureOrNullType ??= futureOrType.instantiate(<DartType>[nullType]);
+    _futureOrNullType ??= InterfaceTypeImpl.explicit(
+      futureOrElement,
+      [nullType],
+      nullabilitySuffix: _nullabilitySuffix,
+    );
     return _futureOrNullType;
   }
 
@@ -155,13 +185,26 @@
 
   @override
   InterfaceType get iterableDynamicType {
-    _iterableDynamicType ??= iterableType.instantiate(<DartType>[dynamicType]);
+    _iterableDynamicType ??= InterfaceTypeImpl.explicit(
+      iterableElement,
+      [dynamicType],
+      nullabilitySuffix: _nullabilitySuffix,
+    );
     return _iterableDynamicType;
   }
 
   @override
+  ClassElement get iterableElement {
+    return _iterableElement ??= _getClassElement(_coreLibrary, 'Iterable');
+  }
+
+  @override
   InterfaceType get iterableObjectType {
-    _iterableObjectType ??= iterableType.instantiate(<DartType>[objectType]);
+    _iterableObjectType ??= InterfaceTypeImpl.explicit(
+      iterableElement,
+      [objectType],
+      nullabilitySuffix: _nullabilitySuffix,
+    );
     return _iterableObjectType;
   }
 
@@ -172,15 +215,29 @@
   }
 
   @override
+  ClassElement get listElement {
+    return _listElement ??= _getClassElement(_coreLibrary, 'List');
+  }
+
+  @override
   InterfaceType get listType {
     _listType ??= _getType(_coreLibrary, "List");
     return _listType;
   }
 
   @override
+  ClassElement get mapElement {
+    return _mapElement ??= _getClassElement(_coreLibrary, 'Map');
+  }
+
+  @override
   InterfaceType get mapObjectObjectType {
-    return _mapObjectObjectType ??=
-        mapType.instantiate(<DartType>[objectType, objectType]);
+    _mapObjectObjectType ??= InterfaceTypeImpl.explicit(
+      mapElement,
+      [objectType, objectType],
+      nullabilitySuffix: _nullabilitySuffix,
+    );
+    return _mapObjectObjectType;
   }
 
   @override
@@ -219,6 +276,11 @@
   }
 
   @override
+  ClassElement get setElement {
+    return _setElement ??= _getClassElement(_coreLibrary, 'Set');
+  }
+
+  @override
   InterfaceType get setType {
     return _setType ??= _getType(_coreLibrary, "Set");
   }
@@ -231,11 +293,20 @@
 
   @override
   InterfaceType get streamDynamicType {
-    _streamDynamicType ??= streamType.instantiate(<DartType>[dynamicType]);
+    _streamDynamicType ??= InterfaceTypeImpl.explicit(
+      streamElement,
+      [dynamicType],
+      nullabilitySuffix: _nullabilitySuffix,
+    );
     return _streamDynamicType;
   }
 
   @override
+  ClassElement get streamElement {
+    return _streamElement ??= _getClassElement(_asyncLibrary, 'Stream');
+  }
+
+  @override
   InterfaceType get streamType {
     _streamType ??= _getType(_asyncLibrary, "Stream");
     return _streamType;
@@ -248,6 +319,11 @@
   }
 
   @override
+  ClassElement get symbolElement {
+    return _symbolElement ??= _getClassElement(_coreLibrary, 'Symbol');
+  }
+
+  @override
   InterfaceType get symbolType {
     _symbolType ??= _getType(_coreLibrary, "Symbol");
     return _symbolType;
@@ -262,6 +338,62 @@
   @override
   VoidType get voidType => VoidTypeImpl.instance;
 
+  @override
+  InterfaceType futureOrType2(DartType valueType) {
+    return futureOrElement.instantiate(
+      typeArguments: [valueType],
+      nullabilitySuffix: _nullabilitySuffix,
+    );
+  }
+
+  @override
+  InterfaceType futureType2(DartType valueType) {
+    return futureElement.instantiate(
+      typeArguments: [valueType],
+      nullabilitySuffix: _nullabilitySuffix,
+    );
+  }
+
+  @override
+  InterfaceType iterableType2(DartType elementType) {
+    return iterableElement.instantiate(
+      typeArguments: [elementType],
+      nullabilitySuffix: _nullabilitySuffix,
+    );
+  }
+
+  @override
+  InterfaceType listType2(DartType elementType) {
+    return listElement.instantiate(
+      typeArguments: [elementType],
+      nullabilitySuffix: _nullabilitySuffix,
+    );
+  }
+
+  @override
+  InterfaceType mapType2(DartType keyType, DartType valueType) {
+    return mapElement.instantiate(
+      typeArguments: [keyType, valueType],
+      nullabilitySuffix: _nullabilitySuffix,
+    );
+  }
+
+  @override
+  InterfaceType setType2(DartType elementType) {
+    return setElement.instantiate(
+      typeArguments: [elementType],
+      nullabilitySuffix: _nullabilitySuffix,
+    );
+  }
+
+  @override
+  InterfaceType streamType2(DartType elementType) {
+    return streamElement.instantiate(
+      typeArguments: [elementType],
+      nullabilitySuffix: _nullabilitySuffix,
+    );
+  }
+
   TypeProviderImpl withNullability(NullabilitySuffix nullabilitySuffix) {
     if (_nullabilitySuffix == nullabilitySuffix) {
       return this;
@@ -270,13 +402,20 @@
         nullabilitySuffix: nullabilitySuffix);
   }
 
-  /// Return the type with the given [name] from the given [library], or
+  /// Return the class with the given [name] from the given [library], or
   /// throw a [StateError] if there is no class with the given name.
-  InterfaceType _getType(LibraryElement library, String name) {
+  ClassElement _getClassElement(LibraryElement library, String name) {
     var element = library.getType(name);
     if (element == null) {
       throw StateError('No definition of type $name');
     }
+    return element;
+  }
+
+  /// Return the type with the given [name] from the given [library], or
+  /// throw a [StateError] if there is no class with the given name.
+  InterfaceType _getType(LibraryElement library, String name) {
+    var element = _getClassElement(library, name);
 
     var typeArguments = const <DartType>[];
     var typeParameters = element.typeParameters;
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 0d8b1c2..4548218 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -57,6 +57,21 @@
           "or removing the unreachable catch clause.");
 
   /**
+   * Users should not create a class named `Function` anymore.
+   */
+  static const HintCode DEPRECATED_FUNCTION_CLASS_DECLARATION = const HintCode(
+      'DEPRECATED_FUNCTION_CLASS_DECLARATION',
+      "Declaring a class named 'Function' is deprecated.",
+      correction: "Try renaming the class.");
+
+  /**
+   * `Function` should not be extended anymore.
+   */
+  static const HintCode DEPRECATED_EXTENDS_FUNCTION = const HintCode(
+      'DEPRECATED_EXTENDS_FUNCTION', "Extending 'Function' is deprecated.",
+      correction: "Try removing 'Function' from the 'extends' clause.");
+
+  /**
    * Parameters:
    * 0: the name of the member
    */
@@ -118,21 +133,6 @@
           hasPublishedDocs: true);
 
   /**
-   * Users should not create a class named `Function` anymore.
-   */
-  static const HintCode DEPRECATED_FUNCTION_CLASS_DECLARATION = const HintCode(
-      'DEPRECATED_FUNCTION_CLASS_DECLARATION',
-      "Declaring a class named 'Function' is deprecated.",
-      correction: "Try renaming the class.");
-
-  /**
-   * `Function` should not be extended anymore.
-   */
-  static const HintCode DEPRECATED_EXTENDS_FUNCTION = const HintCode(
-      'DEPRECATED_EXTENDS_FUNCTION', "Extending 'Function' is deprecated.",
-      correction: "Try removing 'Function' from the 'extends' clause.");
-
-  /**
    * `Function` should not be mixed in anymore.
    */
   static const HintCode DEPRECATED_MIXIN_FUNCTION = const HintCode(
@@ -220,6 +220,18 @@
       correction: "Use explicit type argument(s) for '{0}'.");
 
   /**
+   * When "strict-inference" is enabled, recursive local functions, top-level
+   * functions, methods, and function-typed function parameters must all
+   * specify a return type. See the strict-inference resource:
+   *
+   * 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}'.");
+
+  /**
    * When "strict-inference" is enabled, types in instance creation
    * (constructor calls) must be inferred via the context type, or have type
    * arguments.
@@ -298,6 +310,8 @@
   // The following code produces this diagnostic:
   //
   // ```dart
+  // import 'package:meta/meta.dart';
+  //
   // [!@literal!]
   // var x;
   // ```
@@ -510,7 +524,7 @@
    */
   // #### Description
   //
-  // Any function or method that doesn’t end with either an explicit return or a
+  // Any function or method that doesn't end with either an explicit return or a
   // throw implicitly returns `null`. This is rarely the desired behavior. The
   // analyzer produces this diagnostic when it finds an implicit return.
   //
@@ -683,10 +697,52 @@
       "A package import shouldn't contain '..'.");
 
   /**
-   * A class defined in `dart:async` that was not exported from `dart:core`
-   * before version 2.1 is being referenced via `dart:core` in code that is
-   * expected to run on earlier versions.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when either the class `Future` or
+  // `Stream` is referenced in a library that doesn't import `dart:async` in
+  // code that has an SDK constraint whose lower bound is less than 2.1.0. In
+  // earlier versions, these classes weren't defined in `dart:core`, so the
+  // import was necessary.
+  //
+  // #### Example
+  //
+  // Here's an example of a pubspec that defines an SDK constraint with a lower
+  // bound of less than 2.1.0:
+  //
+  // ```yaml
+  // %uri="pubspec.yaml"
+  // environment:
+  //   sdk: '>=2.0.0 <2.4.0'
+  // ```
+  //
+  // In the package that has that pubspec, code like the following produces this
+  // diagnostic:
+  //
+  // ```dart
+  // void f([!Future!] f) {}
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you don't need to support older versions of the SDK, then you can
+  // increase the SDK constraint to allow the classes to be referenced:
+  //
+  // ```yaml
+  // environment:
+  //   sdk: '>=2.1.0 <2.4.0'
+  // ```
+  //
+  // If you need to support older versions of the SDK, then import the
+  // `dart:async` library.
+  //
+  // ```dart
+  // import 'dart:async';
+  //
+  // void f(Future f) {}
+  // ```
   static const HintCode SDK_VERSION_ASYNC_EXPORTED_FROM_CORE = const HintCode(
       'SDK_VERSION_ASYNC_EXPORTED_FROM_CORE',
       "The class '{0}' wasn't exported from 'dart:core' until version 2.1, "
@@ -695,9 +751,54 @@
           "Try either importing 'dart:async' or updating the SDK constraints.");
 
   /**
-   * An as expression being used in a const context is expected to run on
-   * versions of the SDK that did not support them.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an as expression inside a
+  // [constant context](#constant-context) is found in code that has an SDK
+  // constraint whose lower bound is less than 2.3.2. Using an as expression in
+  // a [constant context](#constant-context) wasn't supported in earlier
+  // versions, so this code won't be able to run against earlier versions of the
+  // SDK.
+  //
+  // #### Example
+  //
+  // Here's an example of a pubspec that defines an SDK constraint with a lower
+  // bound of less than 2.3.2:
+  //
+  // ```yaml
+  // %uri="pubspec.yaml"
+  // environment:
+  //   sdk: '>=2.1.0 <2.4.0'
+  // ```
+  //
+  // In the package that has that pubspec, code like the following generates
+  // this diagnostic:
+  //
+  // ```dart
+  // const num n = 3;
+  // const int i = [!n as int!];
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you don't need to support older versions of the SDK, then you can
+  // ncrease the SDK constraint to allow the expression to be used:
+  //
+  // ```yaml
+  // environment:
+  //   sdk: '>=2.3.2 <2.4.0'
+  // ```
+  //
+  // If you need to support older versions of the SDK, then either rewrite the
+  // code to not use an as expression, or change the code so that the as
+  // expression is not in a [constant context](#constant-context).:
+  //
+  // ```dart
+  // num x = 3;
+  // int y = x as int;
+  // ```
   static const HintCode SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT = const HintCode(
       'SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT',
       "The use of an as expression in a constant expression wasn't "
@@ -706,20 +807,116 @@
       correction: "Try updating the SDK constraints.");
 
   /**
-   * The operator '&', '|' or '^' is being used on boolean values in code that
-   * is expected to run on versions of the SDK that did not support it.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when any use of the `&`, `|` or `^`
+  // operators on the class `bool` inside a
+  // [constant context](#constant-context) is found in code that has an SDK
+  // constraint whose lower bound is less than 2.3.2. Using these operators in a
+  // [constant context](#constant-context) wasn't supported in earlier versions,
+  // so this code won't be able to run against earlier versions of the SDK.
+  //
+  // #### Example
+  //
+  // Here's an example of a pubspec that defines an SDK constraint with a lower
+  // bound of less than 2.3.2:
+  //
+  // ```yaml
+  // %uri="pubspec.yaml"
+  // environment:
+  //   sdk: '>=2.1.0 <2.4.0'
+  // ```
+  //
+  // In the package that has that pubspec, code like the following produces this
+  // diagnostic:
+  //
+  // ```dart
+  // const bool a = true;
+  // const bool b = false;
+  // const bool c = a [!&!] b;
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you don't need to support older versions of the SDK, then you can
+  // increase the SDK constraint to allow the operators to be used:
+  //
+  // ```yaml
+  // environment:
+  //  sdk: '>=2.3.2 <2.4.0'
+  // ```
+  //
+  // If you need to support older versions of the SDK, then either rewrite the
+  // code to not use these operators, or change the code so that the expression
+  // is not in a [constant context](#constant-context).:
+  //
+  // ```dart
+  // const bool a = true;
+  // const bool b = false;
+  // bool c = a & b;
+  // ```
   static const HintCode SDK_VERSION_BOOL_OPERATOR_IN_CONST_CONTEXT = const HintCode(
       'SDK_VERSION_BOOL_OPERATOR_IN_CONST_CONTEXT',
-      "Using the operator '{0}' for 'bool's in a constant expression wasn't "
-          "supported until version 2.3.2, but this code is required to be able "
-          "to run on earlier versions.",
+      "The use of the operator '{0}' for 'bool' operands in a constant context "
+          "wasn't supported until version 2.3.2, but this code is required to "
+          "be able to run on earlier versions.",
       correction: "Try updating the SDK constraints.");
 
   /**
-   * The operator '==' is being used on non-primitive values in code that
-   * is expected to run on versions of the SDK that did not support it.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the operator `==` is used on a
+  // non-primitive type inside a [constant context](#constant-context) is found
+  // in code that has an SDK constraint whose lower bound is less than 2.3.2.
+  // Using this operator in a [constant context](#constant-context) wasn't
+  // supported in earlier versions, so this code won't be able to run against
+  // earlier versions of the SDK.
+  //
+  // #### Example
+  //
+  // Here's an example of a pubspec that defines an SDK constraint with a lower
+  // bound of less than 2.3.2:
+  //
+  // ```yaml
+  // %uri="pubspec.yaml"
+  // environment:
+  //   sdk: '>=2.1.0 <2.4.0'
+  // ```
+  //
+  // In the package that has that pubspec, code like the following produces this
+  // diagnostic:
+  //
+  // ```dart
+  // class C {}
+  // const C a = null;
+  // const C b = null;
+  // const bool same = a [!==!] b;
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you don't need to support older versions of the SDK, then you can
+  // increase the SDK constraint to allow the operator to be used:
+  //
+  // ```yaml
+  // environment:
+  //   sdk: '>=2.3.2 <2.4.0'
+  // ```
+  //
+  // If you need to support older versions of the SDK, then either rewrite the
+  // code to not use the `==` operator, or change the code so that the
+  // expression is not in a [constant context](#constant-context).:
+  //
+  // ```dart
+  // class C {}
+  // const C a = null;
+  // const C b = null;
+  // bool same = a == b;
+  // ```
   static const HintCode SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT =
       const HintCode(
           'SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT',
@@ -729,9 +926,58 @@
           correction: "Try updating the SDK constraints.");
 
   /**
-   * Extension method features are being used in code that is expected to run
-   * on versions of the SDK that did not support them.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an extension declaration or an
+  // extension override is found in code that has an SDK constraint whose lower
+  // bound is less than 2.6.0. Using extensions wasn't supported in earlier
+  // versions, so this code won't be able to run against earlier versions of the
+  // SDK.
+  //
+  // #### Example
+  //
+  // Here's an example of a pubspec that defines an SDK constraint with a lower
+  // bound of less than 2.6.0:
+  //
+  // ```yaml
+  // %uri="pubspec.yaml"
+  // environment:
+  //  sdk: '>=2.4.0 <2.7.0'
+  // ```
+  //
+  // In the package that has that pubspec, code like the following generates
+  // this diagnostic:
+  //
+  // ```dart
+  // [!extension!] E on String {
+  //   void sayHello() {
+  //     print('Hello $this');
+  //   }
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you don't need to support older versions of the SDK, then you can
+  // increase the SDK constraint to allow the syntax to be used:
+  //
+  // ```yaml
+  // environment:
+  //   sdk: '>=2.6.0 <2.7.0'
+  // ```
+  //
+  // If you need to support older versions of the SDK, then rewrite the code to
+  // not make use of extensions. The most common way to do this is to rewrite
+  // the members of the extension as top-level functions (or methods) that take
+  // the value that would have been bound to `this` as a parameter:
+  //
+  // ```dart
+  // void sayHello(String s) {
+  //   print('Hello $s');
+  // }
+  // ```
   static const HintCode SDK_VERSION_EXTENSION_METHODS = const HintCode(
       'SDK_VERSION_EXTENSION_METHODS',
       "Extension methods weren't supported until version 2.6.0, "
@@ -739,9 +985,57 @@
       correction: "Try updating the SDK constraints.");
 
   /**
-   * The operator '>>>' is being used in code that is expected to run on
-   * versions of the SDK that did not support it.
+   * No parameters.
    */
+  /* // #### Description
+  //
+  // The analyzer produces this diagnostic when the operator `>>>` is used in
+  // code that has an SDK constraint whose lower bound is less than 2.X.0. This
+  // operator wasn't supported in earlier versions, so this code won't be able
+  // to run against earlier versions of the SDK.
+  //
+  // #### Example
+  //
+  // Here's an example of a pubspec that defines an SDK constraint with a lower
+  // bound of less than 2.X.0:
+  //
+  // ```yaml
+  // %uri="pubspec.yaml"
+  // environment:
+  //  sdk: '>=2.0.0 <2.4.0'
+  // ```
+  //
+  // In the package that has that pubspec, code like the following produces this
+  // diagnostic:
+  //
+  // ```dart
+  // int x = 3 [!>>>!] 4;
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you don't need to support older versions of the SDK, then you can
+  // increase the SDK constraint to allow the operator to be used:
+  //
+  // ```yaml
+  // environment:
+  //   sdk: '>=2.3.2 <2.4.0'
+  // ```
+  //
+  // If you need to support older versions of the SDK, then rewrite the code to
+  // not use the `>>>` operator:
+  //
+  // ```dart
+  // int x = logicalShiftRight(3, 4);
+  //
+  // int logicalShiftRight(int leftOperand, int rightOperand) {
+  //   int divisor = 1 << rightOperand;
+  //   if (divisor == 0) {
+  //     return 0;
+  //   }
+  //   return leftOperand ~/ divisor;
+  // }
+  // ``` */
   static const HintCode SDK_VERSION_GT_GT_GT_OPERATOR = const HintCode(
       'SDK_VERSION_GT_GT_GT_OPERATOR',
       "The operator '>>>' wasn't supported until version 2.3.2, but this code "
@@ -749,12 +1043,58 @@
       correction: "Try updating the SDK constraints.");
 
   /**
-   * An is expression being used in a const context is expected to run on
-   * versions of the SDK that did not support them.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an is expression inside a
+  // [constant context](#constant-context) is found in code that has an SDK
+  // constraint whose lower bound is less than 2.3.2. Using an is expression in
+  // a [constant context](#constant-context) wasn't supported in earlier
+  // versions, so this code won't be able to run against earlier versions of the
+  // SDK.
+  //
+  // #### Example
+  //
+  // Here's an example of a pubspec that defines an SDK constraint with a lower
+  // bound of less than 2.3.2:
+  //
+  // ```yaml
+  // %uri="pubspec.yaml"
+  // environment:
+  //   sdk: '>=2.1.0 <2.4.0'
+  // ```
+  //
+  // In the package that has that pubspec, code like the following generates
+  // this diagnostic:
+  //
+  // ```dart
+  // const x = 4;
+  // const y = [!x is int!] ? 0 : 1;
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you don't need to support older versions of the SDK, then you can
+  // increase the SDK constraint to allow the expression to be used:
+  //
+  // ```yaml
+  // environment:
+  //   sdk: '>=2.3.2 <2.4.0'
+  // ```
+  //
+  // If you need to support older versions of the SDK, then either rewrite the
+  // code to not use the is operator, or, if that's not possible, change the
+  // code so that the is expression is not in a
+  // [constant context](#constant-context).:
+  //
+  // ```dart
+  // const x = 4;
+  // var y = x is int ? 0 : 1;
+  // ```
   static const HintCode SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT = const HintCode(
       'SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT',
-      "The use of an is expression in a constant expression wasn't supported "
+      "The use of an is expression in a constant context wasn't supported "
           "until version 2.3.2, but this code is required to be able to run on "
           "earlier versions.",
       correction: "Try updating the SDK constraints.");
@@ -765,21 +1105,23 @@
   // #### Description
   //
   // The analyzer produces this diagnostic when a set literal is found in code
-  // that has an SDK constraint whose lower bound is less than 2.2. Set literals
-  // weren't supported in earlier versions, so this code won't be able to run
-  // against earlier versions of the SDK.
+  // that has an SDK constraint whose lower bound is less than 2.2.0. Set
+  // literals weren't supported in earlier versions, so this code won't be able
+  // to run against earlier versions of the SDK.
   //
   // #### Example
   //
-  // In a package that defines the SDK constraint (in the pubspec.yaml file),
-  // with a lower bound of less than 2.2. For example:
+  // Here's an example of a pubspec that defines an SDK constraint with a lower
+  // bound of less than 2.2.0:
   //
   // ```yaml
+  // %uri="pubspec.yaml"
   // environment:
   //   sdk: '>=2.1.0 <2.4.0'
   // ```
   //
-  // The following code generates this diagnostic:
+  // In the package that has that pubspec, code like the following produces this
+  // diagnostic:
   //
   // ```dart
   // var s = [!<int>{}!];
@@ -809,16 +1151,110 @@
       hasPublishedDocs: true);
 
   /**
-   * The type Never is being used in code that is expected to run on versions of
-   * the SDK that did not support it.
+   * No parameters.
    */
+  /* // #### Description
+  //
+  // The analyzer produces this diagnostic when a reference to the class `Never`
+  // is found in code that has an SDK constraint whose lower bound is less than
+  // 2.X.0. This class wasn't defined in earlier versions, so this code won't be
+  // able to run against earlier versions of the SDK.
+  //
+  // #### Example
+  //
+  // Here's an example of a pubspec that defines an SDK constraint with a lower
+  // bound of less than 2.X.0:
+  //
+  // ```yaml
+  // %uri="pubspec.yaml"
+  // environment:
+  //   sdk: '>=2.5.0 <2.6.0'
+  // ```
+  //
+  // In the package that has that pubspec, code like the following produces this
+  // diagnostic:
+  //
+  // ```dart
+  // [!Never!] n;
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you don't need to support older versions of the SDK, then you can
+  // increase the SDK constraint to allow the type to be used:
+  //
+  // ```yaml
+  // environment:
+  //   sdk: '>=2.X.0 <2.7.0'
+  // ```
+  //
+  // If you need to support older versions of the SDK, then rewrite the code to
+  // not reference this class:
+  //
+  // ```dart
+  // dynamic x;
+  // ``` */
   static const HintCode SDK_VERSION_NEVER = const HintCode(
-      'SDK_VERSION_NEVER', "The type Never is not yet supported.");
+      // TODO(brianwilkerson) Replace the message with the following when we know
+      //  when this feature will ship:
+      //    The type 'Never' wasn't supported until version 2.X.0, but this code
+      //    is required to be able to run on earlier versions.
+      'SDK_VERSION_NEVER',
+      "The type Never is not yet supported.");
 
   /**
-   * The for, if or spread element is being used in code that is expected to run
-   * on versions of the SDK that did not support them.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a for, if, or spread element is
+  // found in code that has an SDK constraint whose lower bound is less than
+  // 2.3.0. Using a for, if, or spread element wasn't supported in earlier
+  // versions, so this code won't be able to run against earlier versions of the
+  // SDK.
+  //
+  // #### Example
+  //
+  // Here's an example of a pubspec that defines an SDK constraint with a lower
+  // bound of less than 2.3.0:
+  //
+  // ```yaml
+  // %uri="pubspec.yaml"
+  // environment:
+  //   sdk: '>=2.2.0 <2.4.0'
+  // ```
+  //
+  // In the package that has that pubspec, code like the following generates
+  // this diagnostic:
+  //
+  // ```dart
+  // var digits = [[!for (int i = 0; i < 10; i++) i!]];
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you don't need to support older versions of the SDK, then you can
+  // increase the SDK constraint to allow the syntax to be used:
+  //
+  // ```yaml
+  // environment:
+  //   sdk: '>=2.3.0 <2.4.0'
+  // ```
+  //
+  // If you need to support older versions of the SDK, then rewrite the code to
+  // not make use of those elements:
+  //
+  // ```dart
+  // var digits = _initializeDigits();
+  //
+  // List<int> _initializeDigits() {
+  //   var digits = <int>[];
+  //   for (int i = 0; i < 10; i++) {
+  //     digits.add(i);
+  //   }
+  //   return digits;
+  // }
+  // ```
   static const HintCode SDK_VERSION_UI_AS_CODE = const HintCode(
       'SDK_VERSION_UI_AS_CODE',
       "The for, if, and spread elements weren't supported until version 2.2.2, "
@@ -826,14 +1262,66 @@
       correction: "Try updating the SDK constraints.");
 
   /**
-   * The for, if or spread element is being used in a const context that is
-   * expected to run on versions of the SDK that did not support them.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an if or spread element inside
+  // a [constant context](#constant-context) is found in code that has an
+  // SDK constraint whose lower bound is less than 2.5.0. Using an if or
+  // spread element inside a [constant context](#constant-context) wasn't
+  // supported in earlier versions, so this code won't be able to run against
+  // earlier versions of the SDK.
+  //
+  // #### Example
+  //
+  // Here's an example of a pubspec that defines an SDK constraint with a lower
+  // bound of less than 2.5.0:
+  //
+  // ```yaml
+  // %uri="pubspec.yaml"
+  // environment:
+  //   sdk: '>=2.4.0 <2.6.0'
+  // ```
+  //
+  // In the package that has that pubspec, code like the following generates
+  // this diagnostic:
+  //
+  // ```dart
+  // const a = [1, 2];
+  // const b = [[!...a!]];
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you don't need to support older versions of the SDK, then you can
+  // increase the SDK constraint to allow the syntax to be used:
+  //
+  // ```yaml
+  // environment:
+  //   sdk: '>=2.5.0 <2.6.0'
+  // ```
+  //
+  // If you need to support older versions of the SDK, then rewrite the code to
+  // not make use of those elements:
+  //
+  // ```dart
+  // const a = [1, 2];
+  // const b = [1, 2];
+  // ```
+  //
+  // If that's not possible, change the code so that the element is not in a
+  // [constant context](#constant-context).:
+  //
+  // ```dart
+  // const a = [1, 2];
+  // var b = [...a];
+  // ```
   static const HintCode SDK_VERSION_UI_AS_CODE_IN_CONST_CONTEXT = const HintCode(
       'SDK_VERSION_UI_AS_CODE_IN_CONST_CONTEXT',
-      "The for, if and spread elements weren't supported in constant "
-          "expressions until version 2.5.0, but this code is required to be "
-          "able to run on earlier versions.",
+      "The if and spread elements weren't supported in constant expressions "
+          "until version 2.5.0, but this code is required to be able to run on "
+          "earlier versions.",
       correction: "Try updating the SDK constraints.");
 
   /**
@@ -845,24 +1333,6 @@
       correction: "Use explicit type arguments for '{0}'.");
 
   /**
-   * 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_IN_AS = HintCode(
-      'STRICT_RAW_TYPE_IN_AS',
-      "The generic type '{0}' should have explicit type arguments but doesn't.",
-      correction: "Use explicit type arguments for '{0}'.");
-
-  /**
-   * 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_IN_IS = HintCode(
-      'STRICT_RAW_TYPE_IN_IS',
-      "The generic type '{0}' should have explicit type arguments but doesn't.",
-      correction: "Use explicit type arguments for '{0}'.");
-
-  /**
    * This hint is generated anywhere where a `@sealed` class or mixin is used as
    * a super-type of a class.
    */
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
index 5ad92c2..dbcc657 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
@@ -207,12 +207,79 @@
   static const ParserErrorCode EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE =
       _EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE;
 
+  /**
+   * No parameters.
+   */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an abstract declaration is
+  // declared in an extension. Extensions can declare only concrete members.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // extension E on String {
+  //   int [!a!]();
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Either provide an implementation for the member or remove it.
   static const ParserErrorCode EXTENSION_DECLARES_ABSTRACT_MEMBER =
       _EXTENSION_DECLARES_ABSTRACT_MEMBER;
 
+  /**
+   * No parameters.
+   */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a constructor declaration is
+  // found in an extension. It isn't valid to define a constructor because
+  // extensions aren't classes, and it isn't possible to create an instance of
+  // an extension.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // extension E on String {
+  //   [!E!]() : super();
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove the constructor or replace it with a static method.
   static const ParserErrorCode EXTENSION_DECLARES_CONSTRUCTOR =
       _EXTENSION_DECLARES_CONSTRUCTOR;
 
+  /**
+   * No parameters.
+   */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an instance field declaration is
+  // found in an extension. It isn't valid to define an instance field because
+  // extensions can only add behavior, not state.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // extension E on String {
+  //   String [!s!];
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove the field, make it a static field, or convert it to be a getter,
+  // setter, or method.
   static const ParserErrorCode EXTENSION_DECLARES_INSTANCE_FIELD =
       _EXTENSION_DECLARES_INSTANCE_FIELD;
 
@@ -652,6 +719,9 @@
           correction:
               "Try moving all of the normal parameters before the optional parameters.");
 
+  static const ErrorCode NULL_AWARE_CASCADE_OUT_OF_ORDER =
+      _NULL_AWARE_CASCADE_OUT_OF_ORDER;
+
   static const ParserErrorCode POSITIONAL_AFTER_NAMED_ARGUMENT =
       const ParserErrorCode('POSITIONAL_AFTER_NAMED_ARGUMENT',
           "Positional arguments must occur before named arguments.",
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
index abde3d8..9653453 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
@@ -103,6 +103,7 @@
   _EXTENSION_DECLARES_INSTANCE_FIELD,
   _EXTENSION_DECLARES_ABSTRACT_MEMBER,
   _MIXIN_DECLARES_CONSTRUCTOR,
+  _NULL_AWARE_CASCADE_OUT_OF_ORDER,
 ];
 
 const ParserErrorCode _ABSTRACT_CLASS_MEMBER = const ParserErrorCode(
@@ -481,6 +482,12 @@
     correction:
         "Try removing this native clause and adding @native() or @native('native-name') before the declaration.");
 
+const ParserErrorCode _NULL_AWARE_CASCADE_OUT_OF_ORDER = const ParserErrorCode(
+    'NULL_AWARE_CASCADE_OUT_OF_ORDER',
+    r"The '?..' cascade operator must be first in the cascade sequence.",
+    correction:
+        "Try moving the '?..' operator to be the first cascade operator in the sequence.");
+
 const ParserErrorCode _PREFIX_AFTER_COMBINATOR = const ParserErrorCode(
     'PREFIX_AFTER_COMBINATOR',
     r"The prefix ('as' clause) should come before any show/hide combinators.",
diff --git a/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart b/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
index 58353ea5..cf5639a 100644
--- a/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
@@ -71,7 +71,7 @@
       }
     } else if (target is SimpleIdentifier) {
       // Possible cases: C.n(), p.C() or p.C<>()
-      if (node.operator.type == TokenType.QUESTION_PERIOD) {
+      if (node.isNullAware) {
         // This isn't a constructor invocation because a null aware operator is
         // being used.
       }
diff --git a/pkg/analyzer/lib/src/dart/resolver/exit_detector.dart b/pkg/analyzer/lib/src/dart/resolver/exit_detector.dart
index 0b10058..5e43500 100644
--- a/pkg/analyzer/lib/src/dart/resolver/exit_detector.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/exit_detector.dart
@@ -48,8 +48,7 @@
         operatorType == TokenType.QUESTION_QUESTION_EQ) {
       return false;
     }
-    if (leftHandSide is PropertyAccess &&
-        leftHandSide.operator.type == TokenType.QUESTION_PERIOD) {
+    if (leftHandSide is PropertyAccess && leftHandSide.isNullAware) {
       return false;
     }
     return _nodeExits(node.rightHandSide);
@@ -419,7 +418,7 @@
       if (target.accept(this)) {
         return true;
       }
-      if (node.operator.type == TokenType.QUESTION_PERIOD) {
+      if (node.isNullAware) {
         return false;
       }
     }
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 931287a..2e6c7f7 100644
--- a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
@@ -418,6 +418,7 @@
   static bool _isValidContext(ExtensionOverride node) {
     AstNode parent = node.parent;
     return parent is BinaryExpression && parent.leftOperand == node ||
+        parent is CascadeExpression && parent.target == node ||
         parent is FunctionExpressionInvocation && parent.function == node ||
         parent is IndexExpression && parent.target == node ||
         parent is MethodInvocation && parent.target == node ||
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 8fc4935..a7a4a3e 100644
--- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
@@ -244,9 +244,9 @@
     return false;
   }
 
-  void loopVariable(DeclaredIdentifier loopVariable) {
-    if (loopVariable != null) {
-      flow.add(loopVariable.declaredElement, assigned: true);
+  void loopVariable(DeclaredIdentifier declaredVariable) {
+    if (declaredVariable != null) {
+      flow.add(declaredVariable.declaredElement, assigned: false);
     }
   }
 
@@ -427,6 +427,16 @@
       iterable.accept(this);
 
       assignedVariables.beginNode();
+      if (forLoopParts is ForEachPartsWithIdentifier) {
+        var element = forLoopParts.identifier.staticElement;
+        if (element is VariableElement) {
+          assignedVariables.write(element);
+        }
+      } else if (forLoopParts is ForEachPartsWithDeclaration) {
+        assignedVariables.write(forLoopParts.loopVariable.declaredElement);
+      } else {
+        throw new StateError('Unrecognized for loop parts');
+      }
       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
index 266d3cd..16e1ba9 100644
--- a/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
@@ -275,7 +275,7 @@
               ExecutableElement value = map[memberName];
               ClassElement definingClass = value
                   .getAncestor((Element element) => element is ClassElement);
-              if (!definingClass.type.isObject) {
+              if (!definingClass.isDartCoreObject) {
                 ExecutableElement existingValue = resultMap[memberName];
                 if (existingValue == null ||
                     (existingValue != null && !_isAbstract(value))) {
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 cd09795..f7286de 100644
--- a/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
@@ -8,6 +8,7 @@
 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/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 
@@ -49,12 +50,6 @@
   }
 
   @override
-  visitClassDeclaration(ClassDeclaration node) {
-    _assertLegacyType(node.declaredElement?.type);
-    super.visitClassDeclaration(node);
-  }
-
-  @override
   visitClassMember(ClassMember node) {
     final element = node.declaredElement;
     if (element is ExecutableElement) {
@@ -77,12 +72,6 @@
   }
 
   @override
-  visitEnumDeclaration(EnumDeclaration node) {
-    _assertLegacyType(node.declaredElement?.type);
-    super.visitEnumDeclaration(node);
-  }
-
-  @override
   visitExpression(Expression e) {
     _assertLegacyType(e.staticType);
     super.visitExpression(e);
@@ -146,12 +135,16 @@
       _assertLegacyType(type.bound);
     } else if (type is InterfaceType) {
       type.typeArguments.forEach(_assertLegacyType);
-      type.typeParameters.map((param) => param.type).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.type).forEach(_assertLegacyType);
+      type.typeParameters
+          .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 39a27a4..9244efd 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -3,7 +3,6 @@
 // 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/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
@@ -411,8 +410,9 @@
     }
 
     if (node.isCascaded) {
-      // TODO(brianwilkerson) Report this error and decide how to recover.
-      throw new UnsupportedError('cascaded extension override');
+      // Report this error and recover by treating it like a non-cascade.
+      _resolver.errorReporter.reportErrorForToken(
+          CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE, node.operator);
     }
 
     nameNode.staticElement = member;
@@ -552,7 +552,7 @@
       }
       enclosingClass = receiverType.element;
     } else {
-      receiverType = enclosingClass.type;
+      receiverType = enclosingClass.thisType;
     }
     var target = _inheritance.getMember(receiverType, _currentName);
 
@@ -566,11 +566,19 @@
     if (targetElement != null && targetElement.isStatic) {
       nameNode.staticElement = targetElement;
       _setDynamicResolution(node);
-      _resolver.errorReporter.reportErrorForNode(
-        StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
-        nameNode,
-        [receiverType.displayName],
-      );
+      if (_resolver.enclosingExtension != null) {
+        _resolver.errorReporter.reportErrorForNode(
+            CompileTimeErrorCode
+                .UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE,
+            nameNode,
+            [targetElement.enclosingElement.displayName]);
+      } else {
+        _resolver.errorReporter.reportErrorForNode(
+            StaticTypeWarningCode
+                .UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
+            nameNode,
+            [targetElement.enclosingElement.displayName]);
+      }
       return;
     }
 
@@ -590,9 +598,7 @@
 
   void _resolveReceiverPrefix(MethodInvocation node, SimpleIdentifier receiver,
       PrefixElement prefix, SimpleIdentifier nameNode, String name) {
-    if (node.operator.type == TokenType.QUESTION_PERIOD) {
-      _reportPrefixIdentifierNotFollowedByDot(receiver);
-    }
+    // Note: prefix?.bar is reported as an error in ElementResolver.
 
     if (name == FunctionElement.LOAD_LIBRARY_NAME) {
       var imports = _definingLibrary.getImportsWithPrefix(prefix);
@@ -633,7 +639,7 @@
       return;
     }
 
-    var receiverType = enclosingClass.type;
+    var receiverType = enclosingClass.thisType;
     var target = _inheritance.getMember(
       receiverType,
       _currentName,
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 49aa71d..11e27cf 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -146,14 +146,70 @@
               "explicitly hiding the name in one of the export directives.");
 
   /**
-   * It is a compile time error if there are two applicable extensions defining
-   * the same member and neither is more specific than the other.
-   *
    * Parameters:
    * 0: the name of the member
    * 1: the name of the first declaring extension
    * 2: the name of the second declaring extension
    */
+  // #### Description
+  //
+  // When code refers to a member of an object (for example, `o.m()` or `o.m` or
+  // `o[i]`) where the static type of `o` doesn't declare the member (`m` or
+  // `[]`, for example), then the analyzer tries to find the member in an
+  // extension. For example, if the member is `m`, then the analyzer looks for
+  // extensions that declare a member named `m` and have an extended type that
+  // the static type of `o` can be assigned to. When there's more than one such
+  // extension in scope, the extension whose extended type is most specific is
+  // selected.
+  //
+  // The analyzer produces this diagnostic when none of the extensions has an
+  // extended type that's more specific than the extended types of all of the
+  // other extensions, making the reference to the member ambiguous.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because there's no way to
+  // choose between the member in `E1` and the member in `E2`:
+  //
+  // ```dart
+  // extension E1 on String {
+  //   int get charCount => 1;
+  // }
+  //
+  // extension E2 on String {
+  //   int get charCount => 2;
+  // }
+  //
+  // void f(String s) {
+  //   print(s.[!charCount!]);
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you don't need both extensions, then you can delete or hide one of them.
+  //
+  // If you need both, then explicitly select the one you want to use by using
+  // an extension override:
+  //
+  // ```dart
+  // extension E1 on String {
+  //   int get charCount => length;
+  // }
+  //
+  // extension E2 on String {
+  //   int get charCount => length;
+  // }
+  //
+  // void f(String s) {
+  //   print(E2(s).charCount);
+  // }
+  // ```
+  /*
+   * TODO(brianwilkerson) This message doesn't handle the possible case where
+   *  there are more than 2 extensions, nor does it handle well the case where
+   *  one or more of the extensions is unnamed.
+   */
   static const CompileTimeErrorCode AMBIGUOUS_EXTENSION_MEMBER_ACCESS =
       const CompileTimeErrorCode(
           'AMBIGUOUS_EXTENSION_MEMBER_ACCESS',
@@ -282,7 +338,7 @@
   //
   // ```dart
   // union(a, b) {
-  //   var x = {...a, ...b};
+  //   var x = [!{...a, ...b}!];
   //   return x;
   // }
   // ```
@@ -661,6 +717,86 @@
               "changing the import to not be deferred.");
 
   /**
+   * 16.12.2 Const: An expression of one of the forms !e, e1 && e2 or e1 || e2,
+   * where e, e1 and e2 are constant expressions that evaluate to a boolean
+   * value.
+   */
+  static const CompileTimeErrorCode CONST_EVAL_TYPE_BOOL =
+      const CompileTimeErrorCode(
+          'CONST_EVAL_TYPE_BOOL',
+          "In constant expressions, operands of this operator must be of type "
+              "'bool'.");
+
+  /**
+   * 16.12.2 Const: An expression of one of the forms !e, e1 && e2 or e1 || e2,
+   * where e, e1 and e2 are constant expressions that evaluate to a boolean
+   * value.
+   */
+  static const CompileTimeErrorCode CONST_EVAL_TYPE_BOOL_INT =
+      const CompileTimeErrorCode(
+          'CONST_EVAL_TYPE_BOOL_INT',
+          "In constant expressions, operands of this operator must be of type "
+              "'bool' or 'int'.");
+
+  /**
+   * 16.12.2 Const: An expression of one of the forms e1 == e2 or e1 != e2 where
+   * e1 and e2 are constant expressions that evaluate to a numeric, string or
+   * boolean value or to null.
+   */
+  static const CompileTimeErrorCode CONST_EVAL_TYPE_BOOL_NUM_STRING =
+      const CompileTimeErrorCode(
+          'CONST_EVAL_TYPE_BOOL_NUM_STRING',
+          "In constant expressions, operands of this operator must be of type "
+              "'bool', 'num', 'String' or 'null'.");
+
+  /**
+   * 16.12.2 Const: An expression of one of the forms ~e, e1 ^ e2, e1 & e2,
+   * e1 | e2, e1 >> e2 or e1 << e2, where e, e1 and e2 are constant expressions
+   * that evaluate to an integer value or to null.
+   */
+  static const CompileTimeErrorCode CONST_EVAL_TYPE_INT =
+      const CompileTimeErrorCode(
+          'CONST_EVAL_TYPE_INT',
+          "In constant expressions, operands of this operator must be of type "
+              "'int'.");
+
+  /**
+   * 16.12.2 Const: An expression of one of the forms e, e1 + e2, e1 - e2, e1 *
+   * e2, e1 / e2, e1 ~/ e2, e1 > e2, e1 < e2, e1 >= e2, e1 <= e2 or e1 % e2,
+   * where e, e1 and e2 are constant expressions that evaluate to a numeric
+   * value or to null.
+   */
+  static const CompileTimeErrorCode CONST_EVAL_TYPE_NUM =
+      const CompileTimeErrorCode(
+          'CONST_EVAL_TYPE_NUM',
+          "In constant expressions, operands of this operator must be of type "
+              "'num'.");
+
+  static const CompileTimeErrorCode CONST_EVAL_TYPE_TYPE =
+      const CompileTimeErrorCode(
+          'CONST_EVAL_TYPE_TYPE',
+          "In constant expressions, operands of this operator must be of type "
+              "'Type'.");
+
+  /**
+   * 16.12.2 Const: It is a compile-time error if evaluation of a constant
+   * object results in an uncaught exception being thrown.
+   */
+  static const CompileTimeErrorCode CONST_EVAL_THROWS_EXCEPTION =
+      const CompileTimeErrorCode('CONST_EVAL_THROWS_EXCEPTION',
+          "Evaluation of this constant expression throws an exception.");
+
+  /**
+   * 16.12.2 Const: It is a compile-time error if evaluation of a constant
+   * object results in an uncaught exception being thrown.
+   */
+  static const CompileTimeErrorCode CONST_EVAL_THROWS_IDBZE =
+      const CompileTimeErrorCode(
+          'CONST_EVAL_THROWS_IDBZE',
+          "Evaluation of this constant expression throws an "
+              "IntegerDivisionByZeroException.");
+
+  /**
    * 6.2 Formal Parameters: It is a compile-time error if a formal parameter is
    * declared as a constant variable.
    */
@@ -740,14 +876,6 @@
           correction: "Try declaring the field as final, or adding the keyword "
               "'static'.");
 
-  static const CompileTimeErrorCode CONST_SPREAD_EXPECTED_LIST_OR_SET =
-      const CompileTimeErrorCode('CONST_SPREAD_EXPECTED_LIST_OR_SET',
-          "A list or a set is expected in this spread.");
-
-  static const CompileTimeErrorCode CONST_SPREAD_EXPECTED_MAP =
-      const CompileTimeErrorCode(
-          'CONST_SPREAD_EXPECTED_MAP', "A map is expected in this spread.");
-
   /**
    * 12.8 Maps: It is a compile-time error if the key of an entry in a constant
    * map literal is an instance of a class that implements the operator
@@ -789,85 +917,13 @@
           correction: "Try using a different value for the element, or "
               "removing the keyword 'const' from the set.");
 
-  /**
-   * 16.12.2 Const: An expression of one of the forms !e, e1 && e2 or e1 || e2,
-   * where e, e1 and e2 are constant expressions that evaluate to a boolean
-   * value.
-   */
-  static const CompileTimeErrorCode CONST_EVAL_TYPE_BOOL =
-      const CompileTimeErrorCode(
-          'CONST_EVAL_TYPE_BOOL',
-          "In constant expressions, operands of this operator must be of type "
-              "'bool'.");
+  static const CompileTimeErrorCode CONST_SPREAD_EXPECTED_LIST_OR_SET =
+      const CompileTimeErrorCode('CONST_SPREAD_EXPECTED_LIST_OR_SET',
+          "A list or a set is expected in this spread.");
 
-  /**
-   * 16.12.2 Const: An expression of one of the forms !e, e1 && e2 or e1 || e2,
-   * where e, e1 and e2 are constant expressions that evaluate to a boolean
-   * value.
-   */
-  static const CompileTimeErrorCode CONST_EVAL_TYPE_BOOL_INT =
+  static const CompileTimeErrorCode CONST_SPREAD_EXPECTED_MAP =
       const CompileTimeErrorCode(
-          'CONST_EVAL_TYPE_BOOL_INT',
-          "In constant expressions, operands of this operator must be of type "
-              "'bool' or 'int'.");
-
-  /**
-   * 16.12.2 Const: An expression of one of the forms e1 == e2 or e1 != e2 where
-   * e1 and e2 are constant expressions that evaluate to a numeric, string or
-   * boolean value or to null.
-   */
-  static const CompileTimeErrorCode CONST_EVAL_TYPE_BOOL_NUM_STRING =
-      const CompileTimeErrorCode(
-          'CONST_EVAL_TYPE_BOOL_NUM_STRING',
-          "In constant expressions, operands of this operator must be of type "
-              "'bool', 'num', 'String' or 'null'.");
-
-  /**
-   * 16.12.2 Const: An expression of one of the forms ~e, e1 ^ e2, e1 & e2,
-   * e1 | e2, e1 >> e2 or e1 << e2, where e, e1 and e2 are constant expressions
-   * that evaluate to an integer value or to null.
-   */
-  static const CompileTimeErrorCode CONST_EVAL_TYPE_INT =
-      const CompileTimeErrorCode(
-          'CONST_EVAL_TYPE_INT',
-          "In constant expressions, operands of this operator must be of type "
-              "'int'.");
-
-  /**
-   * 16.12.2 Const: An expression of one of the forms e, e1 + e2, e1 - e2, e1 *
-   * e2, e1 / e2, e1 ~/ e2, e1 > e2, e1 < e2, e1 >= e2, e1 <= e2 or e1 % e2,
-   * where e, e1 and e2 are constant expressions that evaluate to a numeric
-   * value or to null.
-   */
-  static const CompileTimeErrorCode CONST_EVAL_TYPE_NUM =
-      const CompileTimeErrorCode(
-          'CONST_EVAL_TYPE_NUM',
-          "In constant expressions, operands of this operator must be of type "
-              "'num'.");
-
-  static const CompileTimeErrorCode CONST_EVAL_TYPE_TYPE =
-      const CompileTimeErrorCode(
-          'CONST_EVAL_TYPE_TYPE',
-          "In constant expressions, operands of this operator must be of type "
-              "'Type'.");
-
-  /**
-   * 16.12.2 Const: It is a compile-time error if evaluation of a constant
-   * object results in an uncaught exception being thrown.
-   */
-  static const CompileTimeErrorCode CONST_EVAL_THROWS_EXCEPTION =
-      const CompileTimeErrorCode('CONST_EVAL_THROWS_EXCEPTION',
-          "Evaluation of this constant expression throws an exception.");
-
-  /**
-   * 16.12.2 Const: It is a compile-time error if evaluation of a constant
-   * object results in an uncaught exception being thrown.
-   */
-  static const CompileTimeErrorCode CONST_EVAL_THROWS_IDBZE =
-      const CompileTimeErrorCode(
-          'CONST_EVAL_THROWS_IDBZE',
-          "Evaluation of this constant expression throws an "
-              "IntegerDivisionByZeroException.");
+          'CONST_SPREAD_EXPECTED_MAP', "A map is expected in this spread.");
 
   /**
    * 16.12.2 Const: If <i>T</i> is a parameterized type <i>S&lt;U<sub>1</sub>,
@@ -968,15 +1024,6 @@
           correction: "Try calling a different constructor.");
 
   /**
-   * 15.3.1 Typedef: It is a compile-time error if any default values are
-   * specified in the signature of a function type alias.
-   */
-  static const CompileTimeErrorCode DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS =
-      const CompileTimeErrorCode('DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS',
-          "Default parameter values aren't allowed in typedefs.",
-          correction: "Try removing the default value.");
-
-  /**
    * It is an error to call the default List constructor with a length argument
    * and a type argument which is potentially non-nullable.
    */
@@ -988,6 +1035,15 @@
           correction: "Try removing the argument or using 'List.filled'.");
 
   /**
+   * 15.3.1 Typedef: It is a compile-time error if any default values are
+   * specified in the signature of a function type alias.
+   */
+  static const CompileTimeErrorCode DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS =
+      const CompileTimeErrorCode('DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS',
+          "Default parameter values aren't allowed in typedefs.",
+          correction: "Try removing the default value.");
+
+  /**
    * 6.2.1 Required Formals: By means of a function signature that names the
    * parameter and describes its type as a function type. It is a compile-time
    * error if any default values are specified in the signature of such a
@@ -1116,6 +1172,14 @@
               "parameter.");
 
   /**
+   * 16.11 Sets: It is a compile-time error if two elements of a constant set
+   * literal are equal according to their `==` operator (16.27).
+   */
+  static const CompileTimeErrorCode EQUAL_ELEMENTS_IN_CONST_SET =
+      const CompileTimeErrorCode('EQUAL_ELEMENTS_IN_CONST_SET',
+          "Two values in a constant set can't be equal.");
+
+  /**
    * No parameters.
    */
   // #### Description
@@ -1153,14 +1217,6 @@
           hasPublishedDocs: true);
 
   /**
-   * 16.11 Sets: It is a compile-time error if two elements of a constant set
-   * literal are equal according to their `==` operator (16.27).
-   */
-  static const CompileTimeErrorCode EQUAL_ELEMENTS_IN_CONST_SET =
-      const CompileTimeErrorCode('EQUAL_ELEMENTS_IN_CONST_SET',
-          "Two values in a constant set can't be equal.");
-
-  /**
    * SDK implementation libraries can be exported only by other SDK libraries.
    *
    * Parameters:
@@ -1198,7 +1254,7 @@
   // var map = <String, int>{'a': 0, 'b': 1, [!'c'!]};
   // ```
   //
-  // #### Common fix
+  // #### Common fixes
   //
   // If the expression is intended to compute either a key or a value in an
   // entry, fix the issue by replacing the expression with the key or the value.
@@ -1216,21 +1272,6 @@
           hasPublishedDocs: true);
 
   /**
-   * 7.9 Superclasses: It is a compile-time error if the extends clause of a
-   * class <i>C</i> includes a type expression that does not denote a class
-   * available in the lexical scope of <i>C</i>.
-   *
-   * Parameters:
-   * 0: the name of the superclass that was not found
-   */
-  static const CompileTimeErrorCode EXTENDS_NON_CLASS =
-      const CompileTimeErrorCode(
-          'EXTENDS_NON_CLASS', "Classes can only extend other classes.",
-          correction:
-              "Try specifying a different superclass, or removing the extends "
-              "clause.");
-
-  /**
    * 12.2 Null: It is a compile-time error for a class to attempt to extend or
    * implement Null.
    *
@@ -1280,6 +1321,21 @@
               "removing the extends clause.");
 
   /**
+   * 7.9 Superclasses: It is a compile-time error if the extends clause of a
+   * class <i>C</i> includes a type expression that does not denote a class
+   * available in the lexical scope of <i>C</i>.
+   *
+   * Parameters:
+   * 0: the name of the superclass that was not found
+   */
+  static const CompileTimeErrorCode EXTENDS_NON_CLASS =
+      const CompileTimeErrorCode(
+          'EXTENDS_NON_CLASS', "Classes can only extend other classes.",
+          correction:
+              "Try specifying a different superclass, or removing the extends "
+              "clause.");
+
+  /**
    * Parameters:
    * 0: the name of the extension
    */
@@ -1289,17 +1345,43 @@
           correction: "Try replacing it with a valid expression.");
 
   /**
-   * It is for an extension to define a static member and an instance member
-   * with the same base name.
-   *
    * Parameters:
    * 0: the name of the extension defining the conflicting member
    * 1: the name of the conflicting static member
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an extension declaration
+  // contains both an instance member and a static member that have the same
+  // name. The instance member and the static member can't have the same name
+  // because it's unclear which member is being referenced by an unqualified use
+  // of the name within the body of the extension.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // extension E on Object {
+  //   int get a => 0;
+  //   static int [!a!]() => 0;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Rename or remove one of the members:
+  //
+  // ```dart
+  // extension E on Object {
+  //   int get a => 0;
+  //   static int b() => 0;
+  // }
+  // ```
   static const CompileTimeErrorCode EXTENSION_CONFLICTING_STATIC_AND_INSTANCE =
       const CompileTimeErrorCode(
           'EXTENSION_CONFLICTING_STATIC_AND_INSTANCE',
-          "Extension '{0}' can't define static member '{1}' and instance "
+          "Extension '{0}' can't define static member '{1}' and an instance "
               "member with the same name.",
           correction:
               "Try renaming the member to a name that doesn't conflict.");
@@ -1307,6 +1389,33 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an extension declaration
+  // declares a member with the same name as a member declared in the class
+  // `Object`. Such a member can never be used because the member in `Object` is
+  // always found first.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // extension E on String {
+  //   String [!toString!]() => this;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove the member or rename it so that the name doesn't conflict with the
+  // member in `Object`:
+  //
+  // ```dart
+  // extension E on String {
+  //   String displayString() => this;
+  // }
+  // ```
   static const CompileTimeErrorCode EXTENSION_DECLARES_MEMBER_OF_OBJECT =
       const CompileTimeErrorCode(
           'EXTENSION_DECLARES_MEMBER_OF_OBJECT',
@@ -1317,6 +1426,40 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an extension override is the
+  // target of the invocation of a static member. Similar to static members in
+  // classes, the static members of an extension should be accessed using the
+  // name of the extension, not an extension override.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // extension E on String {
+  //   static void staticMethod() {}
+  // }
+  //
+  // void f() {
+  //   E('').[!staticMethod!]();
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Replace the extension override with the name of the extension:
+  //
+  // ```dart
+  // extension E on String {
+  //   static void staticMethod() {}
+  // }
+  //
+  // void f() {
+  //   E.staticMethod();
+  // }
+  // ```
   static const CompileTimeErrorCode EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER =
       const CompileTimeErrorCode(
           'EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER',
@@ -1329,6 +1472,43 @@
    * 0: the type of the argument
    * 1: the extended type
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the argument to an extension
+  // override isn't assignable to the type being extended by the extension.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // extension E on String {
+  //   void method() {}
+  // }
+  //
+  // void f() {
+  //   E([!3!]).method();
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you're using the correct extension, then update the argument to have the
+  // correct type:
+  //
+  // ```dart
+  // extension E on String {
+  //   void method() {}
+  // }
+  //
+  // void f() {
+  //   E(3.toString()).method();
+  // }
+  // ```
+  //
+  // If there's a different extension that's valid for the type of the argument,
+  // then either replace the name of the extension or unwrap the target so that
+  // the correct extension is found.
   static const CompileTimeErrorCode EXTENSION_OVERRIDE_ARGUMENT_NOT_ASSIGNABLE =
       const CompileTimeErrorCode(
           'EXTENSION_OVERRIDE_ARGUMENT_NOT_ASSIGNABLE',
@@ -1338,6 +1518,63 @@
   /**
    * No parameters.
    */
+  static const CompileTimeErrorCode EXTENSION_OVERRIDE_WITH_CASCADE =
+      const CompileTimeErrorCode(
+          'EXTENSION_OVERRIDE_WITH_CASCADE',
+          "Extension overrides have no value so they can't be used as the "
+              "target of a cascade expression.",
+          correction: "Try using '.' instead of '..'.");
+
+  /**
+   * No parameters.
+   */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an extension override is found
+  // that isn't being used to access one of the members of the extension. The
+  // extension override syntax doesn't have any runtime semantics; it only
+  // controls which member is selected at compile time.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // extension E on int {
+  //   int get a => 0;
+  // }
+  //
+  // void f(int i) {
+  //   print([!E(i)!]);
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you want to invoke one of the members of the extension, then add the
+  // invocation:
+  //
+  // ```dart
+  // extension E on int {
+  //   int get a => 0;
+  // }
+  //
+  // void f(int i) {
+  //   print(E(i).a);
+  // }
+  // ```
+  //
+  // If you don't want to invoke a member, then unwrap the target:
+  //
+  // ```dart
+  // extension E on int {
+  //   int get a => 0;
+  // }
+  //
+  // void f(int i) {
+  //   print(i);
+  // }
+  // ```
   static const CompileTimeErrorCode EXTENSION_OVERRIDE_WITHOUT_ACCESS =
       const CompileTimeErrorCode('EXTENSION_OVERRIDE_WITHOUT_ACCESS',
           "An extension override can only be used to access instance members.",
@@ -1404,19 +1641,6 @@
           correction: "Try removing one of the initializations.");
 
   /**
-   * 5 Variables: It is a compile-time error if a final instance variable that
-   * has is initialized by means of an initializing formal of a constructor is
-   * also initialized elsewhere in the same constructor.
-   *
-   * Parameters:
-   * 0: the name of the field in question
-   */
-  static const CompileTimeErrorCode FINAL_INITIALIZED_MULTIPLE_TIMES =
-      const CompileTimeErrorCode('FINAL_INITIALIZED_MULTIPLE_TIMES',
-          "'{0}' is a final field and so can only be set once.",
-          correction: "Try removing all but one of the initializations.");
-
-  /**
    * 7.6.1 Generative Constructors: It is a compile-time error if an
    * initializing formal is used by a function other than a non-redirecting
    * generative constructor.
@@ -1452,6 +1676,47 @@
           correction: "Try using a normal parameter.");
 
   /**
+   * 5 Variables: It is a compile-time error if a final instance variable that
+   * has is initialized by means of an initializing formal of a constructor is
+   * also initialized elsewhere in the same constructor.
+   *
+   * Parameters:
+   * 0: the name of the field in question
+   */
+  static const CompileTimeErrorCode FINAL_INITIALIZED_MULTIPLE_TIMES =
+      const CompileTimeErrorCode('FINAL_INITIALIZED_MULTIPLE_TIMES',
+          "'{0}' is a final field and so can only be set once.",
+          correction: "Try removing all but one of the initializations.");
+
+  static const CompileTimeErrorCode FOR_IN_WITH_CONST_VARIABLE =
+      const CompileTimeErrorCode('FOR_IN_WITH_CONST_VARIABLE',
+          "A for-in loop-variable can't be 'const'.",
+          correction: "Try removing the 'const' modifier from the variable, or "
+              "use a different variable.");
+
+  /**
+   * It is a compile-time error if a generic function type is used as a bound
+   * for a formal type parameter of a class or a function.
+   */
+  static const CompileTimeErrorCode GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND =
+      const CompileTimeErrorCode('GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND',
+          "Generic function types can't be used as type parameter bounds",
+          correction: "Try making the free variable in the function type part"
+              " of the larger declaration signature");
+
+  /**
+   * It is a compile-time error if a generic function type is used as an actual
+   * type argument.
+   */
+  static const CompileTimeErrorCode
+      GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT =
+      const CompileTimeErrorCode(
+          'GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT',
+          "A generic function type can't be a type argument.",
+          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
@@ -1814,24 +2079,6 @@
           correction: "Try using a top-level variable or a field.");
 
   /**
-   * 9. Functions: It is a compile-time error if an async, async* or sync*
-   * modifier is attached to the body of a setter or constructor.
-   */
-  static const CompileTimeErrorCode INVALID_MODIFIER_ON_CONSTRUCTOR =
-      const CompileTimeErrorCode('INVALID_MODIFIER_ON_CONSTRUCTOR',
-          "The modifier '{0}' can't be applied to the body of a constructor.",
-          correction: "Try removing the modifier.");
-
-  /**
-   * 9. Functions: It is a compile-time error if an async, async* or sync*
-   * modifier is attached to the body of a setter or constructor.
-   */
-  static const CompileTimeErrorCode INVALID_MODIFIER_ON_SETTER =
-      const CompileTimeErrorCode('INVALID_MODIFIER_ON_SETTER',
-          "The modifier '{0}' can't be applied to the body of a setter.",
-          correction: "Try removing the modifier.");
-
-  /**
    * TODO(brianwilkerson) Remove this when we have decided on how to report
    * errors in compile-time constants. Until then, this acts as a placeholder
    * for more informative errors.
@@ -1852,6 +2099,53 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an extension override doesn't
+  // have exactly one argument. The argument is the expression used to compute
+  // the value of `this` within the extension method, so there must be one
+  // argument.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because there are no arguments:
+  //
+  // ```dart
+  // extension E on String {
+  //   String join(String other) => '$this $other';
+  // }
+  //
+  // void f() {
+  //   E[!()!].join('b');
+  // }
+  // ```
+  //
+  // And, the following code produces this diagnostic because there's more than
+  // one argument:
+  //
+  // ```dart
+  // extension E on String {
+  //   String join(String other) => '$this $other';
+  // }
+  //
+  // void f() {
+  //   E[!('a', 'b')!].join('c');
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Provide one argument for the extension override:
+  //
+  // ```dart
+  // extension E on String {
+  //   String join(String other) => '$this $other';
+  // }
+  //
+  // void f() {
+  //   E('a').join('b');
+  // }
+  // ```
   static const CompileTimeErrorCode INVALID_EXTENSION_ARGUMENT_COUNT =
       const CompileTimeErrorCode(
           'INVALID_EXTENSION_ARGUMENT_COUNT',
@@ -1878,6 +2172,24 @@
               "(returnType 'Function(' parameters ')').");
 
   /**
+   * 9. Functions: It is a compile-time error if an async, async* or sync*
+   * modifier is attached to the body of a setter or constructor.
+   */
+  static const CompileTimeErrorCode INVALID_MODIFIER_ON_CONSTRUCTOR =
+      const CompileTimeErrorCode('INVALID_MODIFIER_ON_CONSTRUCTOR',
+          "The modifier '{0}' can't be applied to the body of a constructor.",
+          correction: "Try removing the modifier.");
+
+  /**
+   * 9. Functions: It is a compile-time error if an async, async* or sync*
+   * modifier is attached to the body of a setter or constructor.
+   */
+  static const CompileTimeErrorCode INVALID_MODIFIER_ON_SETTER =
+      const CompileTimeErrorCode('INVALID_MODIFIER_ON_SETTER',
+          "The modifier '{0}' can't be applied to the body of a setter.",
+          correction: "Try removing the modifier.");
+
+  /**
    * It is an error if an optional parameter (named or otherwise) with no
    * default value has a potentially non-nullable type. This is produced in
    * cases where there is no valid default value.
@@ -1972,9 +2284,35 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a member declared inside an
+  // extension uses the keyword `covariant` in the declaration of a parameter.
+  // Extensions aren't classes and don't have subclasses, so the keyword serves
+  // no purpose.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // extension E on String {
+  //   void a([!covariant!] int i) {}
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove the 'covariant' keyword:
+  //
+  // ```dart
+  // extension E on String {
+  //   void a(int i) {}
+  // }
+  // ```
   static const CompileTimeErrorCode INVALID_USE_OF_COVARIANT_IN_EXTENSION =
       const CompileTimeErrorCode('INVALID_USE_OF_COVARIANT_IN_EXTENSION',
-          "The 'covariant' keyword can't be used in extensions.",
+          "The 'covariant' keyword can't be used in an extension.",
           correction: "Try removing the 'covariant' keyword.");
 
   /**
@@ -2513,8 +2851,8 @@
   // even though it appears in an implicitly constant list literal:
   //
   // ```dart
-  // int x = 2;
-  // const y = <int>[0, 1, [!x!]];
+  // var x = 2;
+  // var y = const <int>[0, 1, [!x!]];
   // ```
   //
   // #### Common fixes
@@ -2524,17 +2862,17 @@
   // declaration of `x`:
   //
   // ```dart
-  // const int x = 2;
-  // const y = <int>[0, 1, x];
+  // const x = 2;
+  // var y = const <int>[0, 1, x];
   // ```
   //
   // If the expression can't be made a constant, then the list can't be a
   // constant either, so you must change the code so that the list isn't a
-  // constant. In the example above this means removing the `const` keyword from
-  // the declaration of `y`:
+  // constant. In the example above this means removing the `const` keyword
+  // before the list literal:
   //
   // ```dart
-  // int x = 2;
+  // var x = 2;
   // var y = <int>[0, 1, x];
   // ```
   static const CompileTimeErrorCode NON_CONSTANT_LIST_ELEMENT =
@@ -2643,6 +2981,20 @@
           "Initializer expressions in constant constructors must be "
               "constants.");
 
+  /**
+   * 7.6.1 Generative Constructors: Let <i>C</i> be the class in which the
+   * superinitializer appears and let <i>S</i> be the superclass of <i>C</i>.
+   * Let <i>k</i> be a generative constructor. It is a compile-time error if
+   * class <i>S</i> does not declare a generative constructor named <i>S</i>
+   * (respectively <i>S.id</i>)
+   */
+  static const CompileTimeErrorCode NON_GENERATIVE_CONSTRUCTOR =
+      const CompileTimeErrorCode('NON_GENERATIVE_CONSTRUCTOR',
+          "The generative constructor '{0}' expected, but factory found.",
+          correction:
+              "Try calling a different constructor in the superclass, or "
+              "making the called constructor not be a factory constructor.");
+
   static const CompileTimeErrorCode NON_SYNC_FACTORY =
       const CompileTimeErrorCode('NON_SYNC_FACTORY',
           "Factory bodies can't use 'async', 'async*', or 'sync*'.");
@@ -2746,7 +3098,7 @@
   // var s = <String>{...[!m!]};
   // ```
   //
-  // #### Common fix
+  // #### Common fixes
   //
   // The most common fix is to replace the expression with one that produces an
   // iterable object:
@@ -2771,20 +3123,6 @@
               "spread.");
 
   /**
-   * 7.6.1 Generative Constructors: Let <i>C</i> be the class in which the
-   * superinitializer appears and let <i>S</i> be the superclass of <i>C</i>.
-   * Let <i>k</i> be a generative constructor. It is a compile-time error if
-   * class <i>S</i> does not declare a generative constructor named <i>S</i>
-   * (respectively <i>S.id</i>)
-   */
-  static const CompileTimeErrorCode NON_GENERATIVE_CONSTRUCTOR =
-      const CompileTimeErrorCode('NON_GENERATIVE_CONSTRUCTOR',
-          "The generative constructor '{0}' expected, but factory found.",
-          correction:
-              "Try calling a different constructor in the superclass, or "
-              "making the called constructor not be a factory constructor.");
-
-  /**
    * It is an error if the type `T` in the on-catch clause `on T catch` is
    * potentially nullable.
    */
@@ -3053,6 +3391,29 @@
           "'{0}' can't use itself as a mixin.");
 
   /**
+   * 7.6.1 Generative constructors: A generative constructor may be
+   * <i>redirecting</i>, in which case its only action is to invoke another
+   * generative constructor.
+   */
+  static const CompileTimeErrorCode REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR =
+      const CompileTimeErrorCode('REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR',
+          "The constructor '{0}' couldn't be found in '{1}'.",
+          correction: "Try redirecting to a different constructor, or "
+              "defining the constructor named '{0}'.");
+
+  /**
+   * 7.6.1 Generative constructors: A generative constructor may be
+   * <i>redirecting</i>, in which case its only action is to invoke another
+   * generative constructor.
+   */
+  static const CompileTimeErrorCode
+      REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR =
+      const CompileTimeErrorCode(
+          'REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR',
+          "Generative constructor can't redirect to a factory constructor.",
+          correction: "Try redirecting to a different constructor.");
+
+  /**
    * 7.6.2 Factories: It is a compile-time error if <i>k</i> is prefixed with
    * the const modifier but <i>k'</i> is not a constant constructor.
    */
@@ -3078,7 +3439,7 @@
   // The following code produces this diagnostic because `f` is a function:
   //
   // ```dart
-  // C f() {}
+  // C f() => null;
   //
   // class C {
   //   factory C() = [!f!];
@@ -3097,7 +3458,7 @@
   // the constructor to return the value from the constructor's body:
   //
   // ```dart
-  // C f() {}
+  // C f() => null;
   //
   // class C {
   //   factory C() => f();
@@ -3123,29 +3484,6 @@
           correction: "Try redirecting to a different constructor.");
 
   /**
-   * 7.6.1 Generative constructors: A generative constructor may be
-   * <i>redirecting</i>, in which case its only action is to invoke another
-   * generative constructor.
-   */
-  static const CompileTimeErrorCode REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR =
-      const CompileTimeErrorCode('REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR',
-          "The constructor '{0}' couldn't be found in '{1}'.",
-          correction: "Try redirecting to a different constructor, or "
-              "defining the constructor named '{0}'.");
-
-  /**
-   * 7.6.1 Generative constructors: A generative constructor may be
-   * <i>redirecting</i>, in which case its only action is to invoke another
-   * generative constructor.
-   */
-  static const CompileTimeErrorCode
-      REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR =
-      const CompileTimeErrorCode(
-          'REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR',
-          "Generative constructor can't redirect to a factory constructor.",
-          correction: "Try redirecting to a different constructor.");
-
-  /**
    * 5 Variables: A local variable may only be referenced at a source code
    * location that is after its initializer, if any, is complete, or a
    * compile-time error occurs.
@@ -3219,11 +3557,36 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a member declared inside an
+  // extension uses the `super` keyword . Extensions aren't classes and don't
+  // have superclasses, so the `super` keyword serves no purpose.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic:
+  //
+  // ```dart
+  // extension E on Object {
+  //   String get displayString => [!super!].toString();
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove the `super` keyword :
+  //
+  // ```dart
+  // extension E on Object {
+  //   String get displayString => toString();
+  // }
+  // ```
   static const CompileTimeErrorCode SUPER_IN_EXTENSION =
       const CompileTimeErrorCode(
           'SUPER_IN_EXTENSION',
-          "You can't reference 'super' in an extension because extensions do "
-              "not have a superclass.");
+          "The 'super' keyword can't be used in an extension because an "
+              "extension doesn't have a superclass.");
 
   /**
    * 12.15.4 Super Invocation: A super method invocation <i>i</i> has the form
@@ -3292,34 +3655,6 @@
           hasPublishedDocs: true);
 
   /**
-   * It is a compile-time error if a generic function type is used as a bound
-   * for a formal type parameter of a class or a function.
-   */
-  static const CompileTimeErrorCode GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND =
-      const CompileTimeErrorCode('GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND',
-          "Generic function types can't be used as type parameter bounds",
-          correction: "Try making the free variable in the function type part"
-              " of the larger declaration signature");
-
-  static const CompileTimeErrorCode FOR_IN_WITH_CONST_VARIABLE =
-      const CompileTimeErrorCode('FOR_IN_WITH_CONST_VARIABLE',
-          "A for-in loop-variable can't be 'const'.",
-          correction: "Try removing the 'const' modifier from the variable, or "
-              "use a different variable.");
-
-  /**
-   * It is a compile-time error if a generic function type is used as an actual
-   * type argument.
-   */
-  static const CompileTimeErrorCode
-      GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT =
-      const CompileTimeErrorCode(
-          'GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT',
-          "A generic function type can't be a type argument.",
-          correction: "Try removing type parameters from the generic function "
-              "type, or using 'dynamic' as the type argument here.");
-
-  /**
    * 15.3.1 Typedef: Any self reference, either directly, or recursively via
    * another typedef, is a compile time error.
    */
@@ -3364,9 +3699,7 @@
   // ```dart
   // class Point {}
   //
-  // void main() {
-  //   [!Piont!] p;
-  // }
+  // void f([!Piont!] p) {}
   // ```
   //
   // #### Common fixes
@@ -3378,9 +3711,7 @@
   // ```dart
   // class Point {}
   //
-  // void main() {
-  //   Point p;
-  // }
+  // void f(Point p) {}
   // ```
   //
   // If the class is defined but isn't visible, then you probably need to add an
@@ -3432,6 +3763,94 @@
    * 0: the name of the getter that is undefined
    * 1: the name of the extension that was explicitly specified
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an extension override is used to
+  // invoke a getter, but the getter isn't defined by the specified extension.
+  // The analyzer also produces this diagnostic when a static getter is
+  // referenced but isn't defined by the specified extension.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the extension `E`
+  // doesn't declare an instance getter named `b`:
+  //
+  // ```dart
+  // extension E on String {
+  //   String get a => 'a';
+  // }
+  //
+  // extension F on String {
+  //   String get b => 'b';
+  // }
+  //
+  // void f() {
+  //   E('c').[!b!];
+  // }
+  // ```
+  //
+  // The following code produces this diagnostic because the extension `E`
+  // doesn't declare a static getter named `a`:
+  //
+  // ```dart
+  // extension E on String {}
+  //
+  // var x = E.[!a!];
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the name of the getter is incorrect, then change it to the name of an
+  // existing getter:
+  //
+  // ```dart
+  // extension E on String {
+  //   String get a => 'a';
+  // }
+  //
+  // extension F on String {
+  //   String get b => 'b';
+  // }
+  //
+  // void f() {
+  //   E('c').a;
+  // }
+  // ```
+  //
+  // If the name of the getter is correct but the name of the extension is
+  // wrong, then change the name of the extension to the correct name:
+  //
+  // ```dart
+  // extension E on String {
+  //   String get a => 'a';
+  // }
+  //
+  // extension F on String {
+  //   String get b => 'b';
+  // }
+  //
+  // void f() {
+  //   F('c').b;
+  // }
+  // ```
+  //
+  // If the name of the getter and extension are both correct, but the getter
+  // isn't defined, then define the getter:
+  //
+  // ```dart
+  // extension E on String {
+  //   String get a => 'a';
+  //   String get b => 'z';
+  // }
+  //
+  // extension F on String {
+  //   String get b => 'b';
+  // }
+  //
+  // void f() {
+  //   E('c').b;
+  // }
+  // ```
   static const CompileTimeErrorCode UNDEFINED_EXTENSION_GETTER =
       const CompileTimeErrorCode('UNDEFINED_EXTENSION_GETTER',
           "The getter '{0}' isn't defined for the extension '{1}'.",
@@ -3444,6 +3863,94 @@
    * 0: the name of the method that is undefined
    * 1: the name of the extension that was explicitly specified
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an extension override is used to
+  // invoke a method, but the method isn't defined by the specified extension.
+  // The analyzer also produces this diagnostic when a static method is
+  // referenced but isn't defined by the specified extension.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the extension `E`
+  // doesn't declare an instance method named `b`:
+  //
+  // ```dart
+  // extension E on String {
+  //   String a() => 'a';
+  // }
+  //
+  // extension F on String {
+  //   String b() => 'b';
+  // }
+  //
+  // void f() {
+  //   E('c').[!b!]();
+  // }
+  // ```
+  //
+  // The following code produces this diagnostic because the extension `E`
+  // doesn't declare a static method named `a`:
+  //
+  // ```dart
+  // extension E on String {}
+  //
+  // var x = E.[!a!]();
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the name of the method is incorrect, then change it to the name of an
+  // existing method:
+  //
+  // ```dart
+  // extension E on String {
+  //   String a() => 'a';
+  // }
+  //
+  // extension F on String {
+  //   String b() => 'b';
+  // }
+  //
+  // void f() {
+  //   E('c').a();
+  // }
+  // ```
+  //
+  // If the name of the method is correct, but the name of the extension is
+  // wrong, then change the name of the extension to the correct name:
+  //
+  // ```dart
+  // extension E on String {
+  //   String a() => 'a';
+  // }
+  //
+  // extension F on String {
+  //   String b() => 'b';
+  // }
+  //
+  // void f() {
+  //   F('c').b();
+  // }
+  // ```
+  //
+  // If the name of the method and extension are both correct, but the method
+  // isn't defined, then define the method:
+  //
+  // ```dart
+  // extension E on String {
+  //   String a() => 'a';
+  //   String b() => 'z';
+  // }
+  //
+  // extension F on String {
+  //   String b() => 'b';
+  // }
+  //
+  // void f() {
+  //   E('c').b();
+  // }
+  // ```
   static const CompileTimeErrorCode UNDEFINED_EXTENSION_METHOD =
       const CompileTimeErrorCode('UNDEFINED_EXTENSION_METHOD',
           "The method '{0}' isn't defined for the extension '{1}'.",
@@ -3456,6 +3963,96 @@
    * 0: the name of the setter that is undefined
    * 1: the name of the extension that was explicitly specified
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an extension override is used to
+  // invoke a setter, but the setter isn't defined by the specified extension.
+  // The analyzer also produces this diagnostic when a static setter is
+  // referenced but isn't defined by the specified extension.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the extension `E`
+  // doesn't declare an instance setter named `b`:
+  //
+  // ```dart
+  // extension E on String {
+  //   set a(String v) {}
+  // }
+  //
+  // extension F on String {
+  //   set b(String v) {}
+  // }
+  //
+  // void f() {
+  //   E('c').[!b!] = 'd';
+  // }
+  // ```
+  //
+  // The following code produces this diagnostic because the extension `E`
+  // doesn't declare a static setter named `a`:
+  //
+  // ```dart
+  // extension E on String {}
+  //
+  // void f() {
+  //   E.[!a!] = 3;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the name of the setter is incorrect, then change it to the name of an
+  // existing setter:
+  //
+  // ```dart
+  // extension E on String {
+  //   set a(String v) {}
+  // }
+  //
+  // extension F on String {
+  //   set b(String v) {}
+  // }
+  //
+  // void f() {
+  //   E('c').a = 'd';
+  // }
+  // ```
+  //
+  // If the name of the setter is correct, but the name of the extension is
+  // wrong, then change the name of the extension to the correct name:
+  //
+  // ```dart
+  // extension E on String {
+  //   set a(String v) {}
+  // }
+  //
+  // extension F on String {
+  //   set b(String v) {}
+  // }
+  //
+  // void f() {
+  //   F('c').b = 'd';
+  // }
+  // ```
+  //
+  // If the name of the setter and extension are both correct, but the setter
+  // isn't defined, then define the setter:
+  //
+  // ```dart
+  // extension E on String {
+  //   set a(String v) {}
+  //   set b(String v) {}
+  // }
+  //
+  // extension F on String {
+  //   set b(String v) {}
+  // }
+  //
+  // void f() {
+  //   E('c').b = 'd';
+  // }
+  // ```
   static const CompileTimeErrorCode UNDEFINED_EXTENSION_SETTER =
       const CompileTimeErrorCode('UNDEFINED_EXTENSION_SETTER',
           "The setter '{0}' isn't defined for the extension '{1}'.",
@@ -3470,7 +4067,7 @@
   // #### Description
   //
   // The analyzer produces this diagnostic when a method or function invocation
-  // has a named argument, but the method or function being invoked doesn’t
+  // has a named argument, but the method or function being invoked doesn't
   // define a parameter with the same name.
   //
   // #### Example
@@ -3540,6 +4137,18 @@
 
   /**
    * Parameters:
+   * 0: the name of the defining type
+   */
+  static const CompileTimeErrorCode
+      UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE =
+      const CompileTimeErrorCode(
+          'UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE',
+          "Static members from the extended type or one of its superclasses must "
+              "be qualified by the name of the defining type.",
+          correction: "Try adding '{0}.' before the name.");
+
+  /**
+   * Parameters:
    * 0: the URI pointing to a non-existent file
    */
   // #### Description
@@ -4111,7 +4720,7 @@
   // int f(String s) => s.[!len!];
   // ```
   //
-  // #### Common fix
+  // #### Common fixes
   //
   // If the identifier isn't defined, then either define it or replace it with
   // the name of a getter that is defined. The example above can be corrected by
@@ -4149,7 +4758,7 @@
   // int f(List<int> l) => l.[!removeMiddle!]();
   // ```
   //
-  // #### Common fix
+  // #### Common fixes
   //
   // If the identifier isn't defined, then either define it or replace it with
   // the name of a method that is defined. The example above can be corrected by
@@ -4216,31 +4825,25 @@
   // The following code produces this diagnostic:
   //
   // ```dart
-  // class Point {
-  //   int x;
-  //   int y;
-  //   Point(this.x, this.y);
-  //   void shiftBy(Point other) {
-  //     this.x += other.x;
-  //     this.[!z!] += other.y;
+  // class C {
+  //   int x = 0;
+  //   void m(int y) {
+  //     this.[!z!] = y;
   //   }
   // }
   // ```
   //
-  // #### Common fix
+  // #### Common fixes
   //
   // If the identifier isn't defined, then either define it or replace it with
   // the name of a setter that is defined. The example above can be corrected by
   // fixing the spelling of the setter:
   //
   // ```dart
-  // class Point {
-  //   int x;
-  //   int y;
-  //   Point(this.x, this.y);
-  //   void shiftBy(Point other) {
-  //     this.x += other.x;
-  //     this.y += other.y;
+  // class C {
+  //   int x = 0;
+  //   void m(int y) {
+  //     this.x = y;
   //   }
   // }
   // ```
@@ -4509,8 +5112,8 @@
   // The following code produces this diagnostic:
   //
   // ```dart
-  // int f(int x) => x;
-  // num g(num y) => f([!y!]);
+  // String f(String x) => x;
+  // String g(num y) => f([!y!]);
   // ```
   //
   // #### Common fixes
@@ -4519,8 +5122,8 @@
   // example above you might be able to change the type of the parameter `y`:
   //
   // ```dart
-  // int f(int x) => x;
-  // int g(int y) => f(y);
+  // String f(String x) => x;
+  // String g(String y) => f(y);
   // ```
   //
   // If that fix isn't possible, then add code to handle the case where the
@@ -4528,15 +5131,15 @@
   // types to the required type:
   //
   // ```dart
-  // int f(int x) => x;
-  // num g(num y) => f(y.floor());
+  // String f(String x) => x;
+  // String g(num y) => f(y.toString());
   // ```
   //
   // Another approach is to add explicit type tests and fallback code:
   //
   // ```dart
-  // int f(int x) => x;
-  // num g(num y) => f(y is int ? y : 0);
+  // String f(String x) => x;
+  // String g(num y) => f(y is String ? y : '');
   // ```
   //
   // If you believe that the runtime type of the argument will always be the
@@ -4544,8 +5147,8 @@
   // an exception thrown at runtime if you're wrong, then add an explicit cast:
   //
   // ```dart
-  // int f(int x) => x;
-  // num g(num y) => f(y as int);
+  // String f(String x) => x;
+  // String g(num y) => f(y as String);
   // ```
   static const StaticWarningCode ARGUMENT_TYPE_NOT_ASSIGNABLE =
       const StaticWarningCode(
@@ -4832,10 +5435,8 @@
    * 2: the number of additional not initialized variables that aren't listed
    */
   static const StaticWarningCode FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS =
-      const StaticWarningCode(
-          'FINAL_NOT_INITIALIZED_CONSTRUCTOR_3',
-          "The final variables '{0}', '{1}' and '{2}' more must be "
-              "initialized.",
+      const StaticWarningCode('FINAL_NOT_INITIALIZED_CONSTRUCTOR_3',
+          "The final variables '{0}', '{1}' and {2} more must be initialized.",
           correction: "Try adding initializers for the fields.");
 
   /**
@@ -5264,9 +5865,7 @@
   //
   // ```dart
   // f() {}
-  // main() {
-  //   [!f!] v = null;
-  // }
+  // g([!f!] v) {}
   // ```
   //
   // #### Common fixes
@@ -5550,7 +6149,7 @@
               "dynamic.");
 
   /**
-   * It is an error to call a method or getter on an expression of type [Never],
+   * It is an error to call a method or getter on an expression of type `Never`,
    * or to invoke it as if it were a function.
    *
    * Go out of our way to provide a *little* more information here because many
@@ -5588,7 +6187,7 @@
       'USE_OF_VOID_RESULT',
       "The expression here has a type of 'void', and therefore can't be used.",
       correction:
-          "Try checking to see if you are using the correct API; there might "
+          "Try checking to see if you're using the correct API; there might "
           "be a function or call that returns void you didn't expect. Also "
           "check type parameters and variables which might also be void.");
 
diff --git a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
index 0dfad29..2638c00 100644
--- a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
+++ b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
@@ -343,6 +343,9 @@
   void _checkDuplicateIdentifier(
       Map<String, Element> getterScope, SimpleIdentifier identifier,
       {Element element, Map<String, Element> setterScope}) {
+    if (identifier.isSynthetic) {
+      return;
+    }
     element ??= identifier.staticElement;
 
     // Fields define getters and setters, so check them separately.
diff --git a/pkg/analyzer/lib/src/error/inheritance_override.dart b/pkg/analyzer/lib/src/error/inheritance_override.dart
index af4dc3a..8ece3f2 100644
--- a/pkg/analyzer/lib/src/error/inheritance_override.dart
+++ b/pkg/analyzer/lib/src/error/inheritance_override.dart
@@ -135,7 +135,7 @@
       return;
     }
 
-    InterfaceTypeImpl type = classElement.type;
+    InterfaceTypeImpl type = classElement.thisType;
 
     // Add all superinterfaces of the direct supertype.
     if (type.superclass != null) {
@@ -169,11 +169,11 @@
         var fieldList = member.fields;
         for (var field in fieldList.variables) {
           FieldElement fieldElement = field.declaredElement;
-          _checkDeclaredMember(fieldList, libraryUri, fieldElement.getter);
-          _checkDeclaredMember(fieldList, libraryUri, fieldElement.setter);
+          _checkDeclaredMember(field.name, libraryUri, fieldElement.getter);
+          _checkDeclaredMember(field.name, libraryUri, fieldElement.setter);
         }
       } else if (member is MethodDeclaration) {
-        _checkDeclaredMember(member, libraryUri, member.declaredElement,
+        _checkDeclaredMember(member.name, libraryUri, member.declaredElement,
             methodParameterNodes: member.parameters?.parameters);
       }
     }
@@ -221,6 +221,13 @@
         // 2. if the class contains no member named `m`, and the class member
         //    for `noSuchMethod` is the one declared in `Object`, then it's a
         //    compile-time error.
+        // TODO(brianwilkerson) This code catches some cases not caught in
+        //  _checkDeclaredMember, but also duplicates the diagnostic reported
+        //  there in some other cases.
+        // TODO(brianwilkerson) In the case of methods inherited via mixins, the
+        //  diagnostic should be reported on the name of the mixin defining the
+        //  method. In other cases, it should be reported on the name of the
+        //  overriding method. The classNameNode is always wrong.
         if (!typeSystem.isOverrideSubtypeOf(
             concreteElement.type, interfaceElement.type)) {
           reporter.reportErrorForNode(
@@ -228,10 +235,10 @@
             classNameNode,
             [
               name.name,
-              concreteElement.enclosingElement.name,
-              concreteElement.displayName,
               interfaceElement.enclosingElement.name,
-              interfaceElement.displayName,
+              interfaceElement.type.displayName,
+              concreteElement.enclosingElement.name,
+              concreteElement.type.displayName,
             ],
           );
         }
@@ -284,7 +291,7 @@
               member.enclosingElement.name,
               member.type.displayName,
               superMember.enclosingElement.name,
-              superMember.displayName
+              superMember.type.displayName
             ],
           );
         }
diff --git a/pkg/analyzer/lib/src/error/literal_element_verifier.dart b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
index fb2cced..66fa754 100644
--- a/pkg/analyzer/lib/src/error/literal_element_verifier.dart
+++ b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
@@ -4,6 +4,7 @@
 
 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/dart/element/type.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/element/type.dart';
diff --git a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
index 3d1dfab..4592e91 100644
--- a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
+++ b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_algebra.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/resolver.dart';
@@ -80,10 +81,8 @@
 
   void checkTypeName(TypeName node) {
     _checkForTypeArgumentNotMatchingBounds(node);
-    if (node.parent is ConstructorName &&
-        node.parent.parent is InstanceCreationExpression) {
-      _checkForInferenceFailureOnInstanceCreation(node, node.parent.parent);
-    } else {
+    if (node.parent is! ConstructorName ||
+        node.parent.parent is! InstanceCreationExpression) {
       _checkForRawTypeName(node);
     }
   }
@@ -147,27 +146,6 @@
     }
   }
 
-  /// Checks a type on an instance creation expression for an inference
-  /// failure, and reports the appropriate error if
-  /// [AnalysisOptionsImpl.strictInference] is set.
-  ///
-  /// This checks if [node] refers to a generic type and does not have explicit
-  /// or inferred type arguments. When that happens, it reports a
-  /// HintMode.INFERENCE_FAILURE_ON_INSTANCE_CREATION error.
-  void _checkForInferenceFailureOnInstanceCreation(
-      TypeName node, InstanceCreationExpression inferenceContextNode) {
-    if (!_options.strictInference || node == null) return;
-    if (node.typeArguments != null) {
-      // Type has explicit type arguments.
-      return;
-    }
-    if (_isMissingTypeArguments(
-        node, node.type, node.name.staticElement, inferenceContextNode)) {
-      _errorReporter.reportErrorForNode(
-          HintCode.INFERENCE_FAILURE_ON_INSTANCE_CREATION, node, [node.type]);
-    }
-  }
-
   /// Checks a type annotation for a raw generic type, and reports the
   /// appropriate error if [AnalysisOptionsImpl.strictRawTypes] is set.
   ///
@@ -194,12 +172,9 @@
     if (_isMissingTypeArguments(
         node, node.type, node.name.staticElement, null)) {
       AstNode unwrappedParent = parentEscapingTypeArguments(node);
-      if (unwrappedParent is AsExpression) {
-        _errorReporter.reportErrorForNode(
-            HintCode.STRICT_RAW_TYPE_IN_AS, node, [node.type]);
-      } else if (unwrappedParent is IsExpression) {
-        _errorReporter.reportErrorForNode(
-            HintCode.STRICT_RAW_TYPE_IN_IS, node, [node.type]);
+      if (unwrappedParent is AsExpression || unwrappedParent is IsExpression) {
+        // Do not report a "Strict raw type" error in this case; too noisy.
+        // See https://github.com/dart-lang/language/blob/master/resources/type-system/strict-raw-types.md#conditions-for-a-raw-type-hint
       } else {
         _errorReporter
             .reportErrorForNode(HintCode.STRICT_RAW_TYPE, node, [node.type]);
@@ -238,8 +213,6 @@
             'Unexpected element associated with parameterized type: '
             '${element.runtimeType}');
       }
-      var parameterTypes =
-          parameterElements.map<DartType>((p) => p.type).toList();
       List<DartType> arguments = type.typeArguments;
       // iterate over each bounded type parameter and corresponding argument
       NodeList<TypeAnnotation> argumentNodes =
@@ -248,7 +221,7 @@
       int loopThroughIndex =
           math.min(typeArguments.length, parameterElements.length);
       bool shouldSubstitute =
-          arguments.isNotEmpty && arguments.length == parameterTypes.length;
+          arguments.isNotEmpty && arguments.length == parameterElements.length;
       for (int i = 0; i < loopThroughIndex; i++) {
         DartType argType = typeArguments[i];
         TypeAnnotation argumentNode =
@@ -265,7 +238,8 @@
         DartType boundType = parameterElements[i].bound;
         if (argType != null && boundType != null) {
           if (shouldSubstitute) {
-            boundType = boundType.substitute2(arguments, parameterTypes);
+            boundType = Substitution.fromPairs(parameterElements, arguments)
+                .substituteType(boundType);
           }
 
           if (!_typeSystem.isSubtypeOf(argType, boundType)) {
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index fa944a9..5d94e1b 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -23,7 +23,6 @@
         Message,
         MessageCode,
         messageConstConstructorWithBody,
-        messageConstMethod,
         messageConstructorWithReturnType,
         messageConstructorWithTypeParameters,
         messageDirectiveAfterDeclaration,
@@ -1607,11 +1606,6 @@
       throw new UnimplementedError();
     }
 
-    if (modifiers?.constKeyword != null) {
-      // This error is also reported in OutlineBuilder.endMethod
-      handleRecoverableError(
-          messageConstMethod, modifiers.constKeyword, modifiers.constKeyword);
-    }
     checkFieldFormalParameters(parameters);
     currentDeclarationMembers.add(ast.methodDeclaration(
         comment,
diff --git a/pkg/analyzer/lib/src/generated/declaration_resolver.dart b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
index 6184e13..25b6dcc 100644
--- a/pkg/analyzer/lib/src/generated/declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
@@ -462,7 +462,6 @@
       // Work around dartbug.com/28515.
       // TODO(paulberry): remove this once dartbug.com/28515 is fixed.
       var element = new TypeParameterElementImpl.forNode(node.name);
-      element.type = new TypeParameterTypeImpl(element);
       node.name?.staticElement = element;
     } else {
       TypeParameterElement element =
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index e91190e..6e95ad6 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -645,6 +645,7 @@
     AstNode parent = node.parent;
     if (parent is Annotation) {
       _resolveAnnotationElement(parent);
+      return;
     }
     //
     // Otherwise, the prefix is really an expression that happens to be a simple
@@ -692,8 +693,10 @@
       return;
     } else if (target is ExtensionOverride) {
       if (node.isCascaded) {
-        // TODO(brianwilkerson) Report this error and decide how to recover.
-        throw new UnsupportedError('cascaded extension override');
+        // Report this error and recover by treating it like a non-cascade.
+        _resolver.errorReporter.reportErrorForToken(
+            CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE,
+            node.operator);
       }
       ExtensionElement element = target.extensionName.staticElement;
       SimpleIdentifier propertyName = node.propertyName;
@@ -860,7 +863,7 @@
     if (node.inSetterContext() &&
         node.inGetterContext() &&
         enclosingClass != null) {
-      InterfaceType enclosingType = enclosingClass.type;
+      InterfaceType enclosingType = enclosingClass.thisType;
       var propertyResolver = _newPropertyResolver();
       propertyResolver.resolve(null, enclosingType, node.name, node);
       node.auxiliaryElements = AuxiliaryElements(
@@ -956,6 +959,20 @@
     resolveMetadata(node);
   }
 
+  /// If the [element] is not static, report the error on the [identifier].
+  void _checkForStaticAccessToInstanceMember(
+    SimpleIdentifier identifier,
+    ExecutableElement element,
+  ) {
+    if (element.isStatic) return;
+
+    _resolver.errorReporter.reportErrorForNode(
+      StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER,
+      identifier,
+      [identifier.name],
+    );
+  }
+
   /**
    * Check that the given index [expression] was resolved, otherwise a
    * [StaticTypeWarningCode.UNDEFINED_OPERATOR] is generated. The [target] is
@@ -1132,18 +1149,6 @@
   }
 
   /**
-   * Return `true` if the given [element] is a static element.
-   */
-  bool _isStatic(Element element) {
-    if (element is ExecutableElement) {
-      return element.isStatic;
-    } else if (element is PropertyInducingElement) {
-      return element.isStatic;
-    }
-    return false;
-  }
-
-  /**
    * Return `true` if the given [node] can validly be resolved to a prefix:
    * * it is the prefix in an import directive, or
    * * it is the prefix in a prefixed identifier.
@@ -1155,7 +1160,8 @@
     } else if (parent is PrefixedIdentifier) {
       return true;
     } else if (parent is MethodInvocation) {
-      return identical(parent.target, node);
+      return identical(parent.target, node) &&
+          parent.operator?.type == TokenType.PERIOD;
     }
     return false;
   }
@@ -1501,34 +1507,6 @@
   }
 
   /**
-   * Given that we are accessing a property of the given [classElement] with the
-   * given [propertyName], return the element that represents the property.
-   */
-  ResolutionResult _resolveElement(
-      ClassElement classElement, SimpleIdentifier propertyName) {
-    String name = propertyName.name;
-    if (propertyName.inSetterContext()) {
-      var element = classElement.getSetter(name);
-      if (element != null && element.isAccessibleIn(_definingLibrary)) {
-        return ResolutionResult(property: element.variable);
-      }
-    }
-    {
-      var element = classElement.getGetter(name);
-      if (element != null && element.isAccessibleIn(_definingLibrary)) {
-        return ResolutionResult(property: element.variable);
-      }
-    }
-    {
-      var element = classElement.getMethod(name);
-      if (element != null && element.isAccessibleIn(_definingLibrary)) {
-        return ResolutionResult(function: element);
-      }
-    }
-    return ResolutionResult.none;
-  }
-
-  /**
    * Given a [node] that can have annotations associated with it, resolve the
    * annotations in the element model representing annotations to the node.
    */
@@ -1536,195 +1514,256 @@
     _resolveAnnotations(node.metadata);
   }
 
-  /**
-   * Given that we are accessing a property of the given [targetType] with the
-   * given [propertyName], return the element that represents the property. The
-   * [target] is the target of the invocation ('e').
-   */
-  ResolutionResult _resolveProperty(
-      Expression target, DartType targetType, SimpleIdentifier propertyName) {
-    var propertyResolver = _newPropertyResolver();
-    propertyResolver.resolve(
-        target, targetType, propertyName.name, propertyName);
-    ResolutionResult result = ResolutionResult.none;
-    if (propertyName.inSetterContext()) {
-      result = propertyResolver.setterResult;
-    }
-    if (result.isNone) {
-      result = propertyResolver.getterResult;
-    }
-    return result;
-  }
-
   void _resolvePropertyAccess(
       Expression target, SimpleIdentifier propertyName, bool isCascaded) {
     DartType staticType = _getStaticType(target);
+
     //
     // If this property access is of the form 'E.m' where 'E' is an extension,
     // then look for the member in the extension. This does not apply to
     // conditional property accesses (i.e. 'C?.m').
     //
-    ResolutionResult result = ResolutionResult.none;
     if (target is Identifier && target.staticElement is ExtensionElement) {
-      ExecutableElement staticElement;
       ExtensionElement extension = target.staticElement;
       String memberName = propertyName.name;
-      if (propertyName.inSetterContext()) {
-        staticElement = extension.getSetter(memberName);
-      }
-      staticElement ??= extension.getGetter(memberName);
-      staticElement ??= extension.getMethod(memberName);
-      if (staticElement == null) {
-        if (propertyName.inSetterContext()) {
-          _resolver.errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER,
-              propertyName,
-              [memberName, extension.name]);
+
+      if (propertyName.inGetterContext()) {
+        ExecutableElement element;
+        element ??= extension.getGetter(memberName);
+        element ??= extension.getMethod(memberName);
+        if (element != null) {
+          propertyName.staticElement = element;
+          _checkForStaticAccessToInstanceMember(propertyName, element);
         } else {
           _resolver.errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER,
-              propertyName,
-              [memberName, extension.name]);
-        }
-      } else if (!staticElement.isStatic) {
-        _resolver.errorReporter.reportErrorForNode(
-            StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER,
+            CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER,
             propertyName,
-            [memberName]);
-      }
-      if (staticElement != null) {
-        if (staticElement is PropertyAccessorElement) {
-          result = ResolutionResult(property: staticElement.variable);
-        } else if (staticElement is MethodElement) {
-          result = ResolutionResult(function: staticElement);
+            [memberName, extension.name],
+          );
         }
       }
+
+      if (propertyName.inSetterContext()) {
+        var element = extension.getSetter(memberName);
+        if (element != null) {
+          propertyName.staticElement = element;
+          _checkForStaticAccessToInstanceMember(propertyName, element);
+        } else {
+          _resolver.errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER,
+            propertyName,
+            [memberName, extension.name],
+          );
+        }
+      }
+
+      return;
     }
+
     //
     // If this property access is of the form 'C.m' where 'C' is a class,
     // then we don't call resolveProperty(...) which walks up the class
     // hierarchy, instead we just look for the member in the type only.  This
     // does not apply to conditional property accesses (i.e. 'C?.m').
     //
-    if (result.isNone) {
-      ClassElement typeReference = getTypeReference(target);
-      if (typeReference != null) {
-        if (isCascaded) {
-          typeReference = _typeType.element;
+    ClassElement typeReference = getTypeReference(target);
+    if (typeReference != null) {
+      if (isCascaded) {
+        typeReference = _typeType.element;
+      }
+
+      if (propertyName.inGetterContext()) {
+        ExecutableElement element;
+
+        if (element == null) {
+          var getter = typeReference.getGetter(propertyName.name);
+          if (getter != null && getter.isAccessibleIn(_definingLibrary)) {
+            element = getter;
+          }
         }
-        result = _resolveElement(typeReference, propertyName);
-      } else {
-        if (target is SuperExpression) {
-          ExecutableElement staticElement;
-          if (staticType is InterfaceTypeImpl) {
-            staticElement = staticType.lookUpInheritedMember(
-                propertyName.name, _definingLibrary,
-                setter: propertyName.inSetterContext(),
-                concrete: true,
-                forSuperInvocation: true);
+
+        if (element == null) {
+          var method = typeReference.getMethod(propertyName.name);
+          if (method != null && method.isAccessibleIn(_definingLibrary)) {
+            element = method;
+          }
+        }
+
+        if (element != null) {
+          propertyName.staticElement = element;
+          _checkForStaticAccessToInstanceMember(propertyName, element);
+        } else {
+          _resolver.errorReporter.reportErrorForNode(
+            StaticTypeWarningCode.UNDEFINED_GETTER,
+            propertyName,
+            [propertyName.name, typeReference.name],
+          );
+        }
+      }
+
+      if (propertyName.inSetterContext()) {
+        ExecutableElement element;
+
+        var setter = typeReference.getSetter(propertyName.name);
+        if (setter != null && setter.isAccessibleIn(_definingLibrary)) {
+          element = setter;
+        }
+
+        if (element != null) {
+          propertyName.staticElement = element;
+          _checkForStaticAccessToInstanceMember(propertyName, element);
+        } else {
+          var getter = typeReference.getGetter(propertyName.name);
+          if (getter != null) {
+            propertyName.staticElement = getter;
+            // The error will be reported in ErrorVerifier.
+          } else {
+            _resolver.errorReporter.reportErrorForNode(
+              StaticTypeWarningCode.UNDEFINED_SETTER,
+              propertyName,
+              [propertyName.name, typeReference.name],
+            );
+          }
+        }
+      }
+
+      return;
+    }
+
+    if (target is SuperExpression) {
+      if (staticType is InterfaceTypeImpl) {
+        if (propertyName.inGetterContext()) {
+          var element = staticType.lookUpInheritedMember(
+              propertyName.name, _definingLibrary,
+              setter: false, concrete: true, forSuperInvocation: true);
+
+          if (element != null) {
+            propertyName.staticElement = element;
+          } else {
             // We were not able to find the concrete dispatch target.
             // But we would like to give the user at least some resolution.
             // So, we retry without the "concrete" requirement.
-            if (staticElement == null) {
-              staticElement = staticType.lookUpInheritedMember(
-                  propertyName.name, _definingLibrary,
-                  setter: propertyName.inSetterContext(), concrete: false);
-              if (staticElement != null) {
-                ClassElementImpl receiverSuperClass =
-                    AbstractClassElementImpl.getImpl(
-                  staticType.element.supertype.element,
+            element = staticType.lookUpInheritedMember(
+                propertyName.name, _definingLibrary,
+                setter: false, concrete: false);
+            if (element != null) {
+              propertyName.staticElement = element;
+              ClassElementImpl receiverSuperClass =
+                  AbstractClassElementImpl.getImpl(
+                staticType.element.supertype.element,
+              );
+              if (!receiverSuperClass.hasNoSuchMethod) {
+                _resolver.errorReporter.reportErrorForNode(
+                  CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
+                  propertyName,
+                  [element.kind.displayName, propertyName.name],
                 );
-                if (!receiverSuperClass.hasNoSuchMethod) {
-                  _resolver.errorReporter.reportErrorForNode(
-                      CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
-                      propertyName,
-                      [staticElement.kind.displayName, propertyName.name]);
-                }
               }
+            } else {
+              _resolver.errorReporter.reportErrorForNode(
+                StaticTypeWarningCode.UNDEFINED_SUPER_GETTER,
+                propertyName,
+                [propertyName.name, staticType.displayName],
+              );
             }
           }
-          if (staticElement is PropertyAccessorElement) {
-            result = ResolutionResult(property: staticElement.variable);
-          } else if (staticElement is MethodElement) {
-            result = ResolutionResult(function: staticElement);
+        }
+
+        if (propertyName.inSetterContext()) {
+          var element = staticType.lookUpInheritedMember(
+              propertyName.name, _definingLibrary,
+              setter: true, concrete: true, forSuperInvocation: true);
+
+          if (element != null) {
+            propertyName.staticElement = element;
+          } else {
+            // We were not able to find the concrete dispatch target.
+            // But we would like to give the user at least some resolution.
+            // So, we retry without the "concrete" requirement.
+            element = staticType.lookUpInheritedMember(
+                propertyName.name, _definingLibrary,
+                setter: true, concrete: false);
+            if (element != null) {
+              propertyName.staticElement = element;
+              ClassElementImpl receiverSuperClass =
+                  AbstractClassElementImpl.getImpl(
+                staticType.element.supertype.element,
+              );
+              if (!receiverSuperClass.hasNoSuchMethod) {
+                _resolver.errorReporter.reportErrorForNode(
+                  CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
+                  propertyName,
+                  [element.kind.displayName, propertyName.name],
+                );
+              }
+            } else {
+              _resolver.errorReporter.reportErrorForNode(
+                StaticTypeWarningCode.UNDEFINED_SUPER_SETTER,
+                propertyName,
+                [propertyName.name, staticType.displayName],
+              );
+            }
           }
-        } else {
-          result = _resolveProperty(target, staticType, propertyName);
         }
       }
-    }
-    // Might be part of an annotation, record property element only if exists.
-    // Error was already reported in validateAnnotationElement().
-    if (target.parent.parent is Annotation) {
-      if (result.isSingle) {
-        propertyName.staticElement = result.getter;
-      }
+
       return;
     }
-    propertyName.staticElement =
-        (propertyName.inSetterContext() ? result.setter : null) ??
-            result.getter;
-    if (_shouldReportInvalidMember(staticType, result)) {
-      if (staticType is FunctionType &&
-          propertyName.name == FunctionElement.CALL_METHOD_NAME) {
-        return;
-      }
-      Element enclosingElement = staticType.element;
-      bool isStaticProperty = _isStatic(enclosingElement);
-      // Special getter cases.
-      if (propertyName.inGetterContext()) {
-        if (!isStaticProperty && enclosingElement is ClassElement) {
-          InterfaceType targetType = enclosingElement.type;
-          if (targetType != null &&
-              targetType.isDartCoreFunction &&
-              propertyName.name == FunctionElement.CALL_METHOD_NAME) {
-            return;
-          } else if (enclosingElement.isEnum && propertyName.name == "_name") {
-            _resolver.errorReporter.reportErrorForNode(
-                CompileTimeErrorCode.ACCESS_PRIVATE_ENUM_FIELD,
-                propertyName,
-                [propertyName.name]);
-            return;
-          }
-        }
-      }
-      Element declaringElement = staticType.isVoid ? null : enclosingElement;
-      if (propertyName.inSetterContext()) {
-        ErrorCode errorCode;
-        var arguments = [propertyName.name, staticType.displayName];
-        if (target is SuperExpression) {
-          errorCode = StaticTypeWarningCode.UNDEFINED_SUPER_SETTER;
+
+    if (staticType == null || staticType.isDynamic) {
+      return;
+    }
+
+    if (staticType.isVoid) {
+      _resolver.errorReporter.reportErrorForNode(
+        StaticWarningCode.USE_OF_VOID_RESULT,
+        propertyName,
+      );
+      return;
+    }
+
+    var propertyResolver = _newPropertyResolver();
+    propertyResolver.resolve(
+        target, staticType, propertyName.name, propertyName);
+
+    if (propertyName.inGetterContext()) {
+      var getterResult = propertyResolver.getterResult;
+      if (getterResult.isSingle) {
+        propertyName.staticElement = getterResult.getter;
+      } else if (getterResult.isNone) {
+        if (staticType is FunctionType &&
+            propertyName.name == FunctionElement.CALL_METHOD_NAME) {
+          // Referencing `.call` on a `Function` type is OK.
+        } else if (staticType is InterfaceType &&
+            staticType.isDartCoreFunction &&
+            propertyName.name == FunctionElement.CALL_METHOD_NAME) {
+          // Referencing `.call` on a `Function` type is OK.
         } else {
-          if (staticType.isVoid) {
-            errorCode = StaticWarningCode.USE_OF_VOID_RESULT;
-            arguments = [];
-          } else {
-            errorCode = StaticTypeWarningCode.UNDEFINED_SETTER;
-          }
-        }
-        _recordUndefinedNode(
-            declaringElement, errorCode, propertyName, arguments);
-      } else if (propertyName.inGetterContext()) {
-        ErrorCode errorCode;
-        var arguments = [propertyName.name, staticType.displayName];
-        if (target is SuperExpression) {
-          errorCode = StaticTypeWarningCode.UNDEFINED_SUPER_GETTER;
-        } else {
-          if (staticType.isVoid) {
-            errorCode = StaticWarningCode.USE_OF_VOID_RESULT;
-            arguments = [];
-          } else {
-            errorCode = StaticTypeWarningCode.UNDEFINED_GETTER;
-          }
-        }
-        _recordUndefinedNode(
-            declaringElement, errorCode, propertyName, arguments);
-      } else {
-        _recordUndefinedNode(
-            declaringElement,
-            StaticWarningCode.UNDEFINED_IDENTIFIER,
+          _resolver.errorReporter.reportErrorForNode(
+            StaticTypeWarningCode.UNDEFINED_GETTER,
             propertyName,
-            [propertyName.name]);
+            [propertyName.name, staticType.displayName],
+          );
+        }
+      }
+    }
+
+    if (propertyName.inSetterContext()) {
+      var setterResult = propertyResolver.setterResult;
+      if (setterResult.isSingle) {
+        propertyName.staticElement = setterResult.setter;
+      } else if (setterResult.isNone) {
+        var getter = propertyResolver.getterResult.getter;
+        if (getter != null) {
+          propertyName.staticElement = getter;
+          // A more specific error will be reported in ErrorVerifier.
+        } else {
+          _resolver.errorReporter.reportErrorForNode(
+            StaticTypeWarningCode.UNDEFINED_SETTER,
+            propertyName,
+            [propertyName.name, staticType.displayName],
+          );
+        }
       }
     }
   }
@@ -1750,7 +1789,7 @@
           if (enclosingClass != null) {
             var propertyResolver = _newPropertyResolver();
             propertyResolver.resolve(
-                null, enclosingClass.type, identifier.name, identifier);
+                null, enclosingClass.thisType, identifier.name, identifier);
             setter = propertyResolver.setterResult.setter;
           }
         }
@@ -1783,7 +1822,7 @@
           return null;
         }
       } else {
-        enclosingType = enclosingClass.type;
+        enclosingType = enclosingClass.thisType;
       }
       if (element == null && enclosingType != null) {
         var propertyResolver = _newPropertyResolver();
@@ -2019,8 +2058,8 @@
       if (result.isSingle) {
         if (result.getter != null) {
           getterResult = result;
-        } else {
-          assert(result.setter != null);
+        }
+        if (result.setter != null) {
           setterResult = result;
         }
       } else if (result.isAmbiguous) {
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index dd79796..ec27a69 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -2,34 +2,23 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:async';
 import 'dart:collection';
 import 'dart:typed_data';
 
 import 'package:analyzer/dart/analysis/features.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/source/error_processor.dart';
-import 'package:analyzer/src/cancelable_future.dart';
-import 'package:analyzer/src/context/builder.dart' show EmbedderYamlLocator;
-import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/generated/constant.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/timestamped_data.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
-import 'package:analyzer/src/plugin/resolver_provider.dart';
 import 'package:analyzer/src/services/lint.dart';
 import 'package:analyzer/src/summary/api_signature.dart';
-import 'package:analyzer/src/task/api/model.dart';
 import 'package:front_end/src/fasta/scanner/token.dart';
 import 'package:path/path.dart' as pathos;
 import 'package:pub_semver/pub_semver.dart';
@@ -80,10 +69,6 @@
 /// also be used to perform an analysis based on a proposed future state, such as
 /// the state after a refactoring.
 abstract class AnalysisContext {
-  /// The file resolver provider used to override the way file URI's are
-  /// resolved in some contexts.
-  ResolverProvider fileResolverProvider;
-
   /// Return the set of analysis options controlling the behavior of this
   /// context. Clients should not modify the returned set of options.
   AnalysisOptions get analysisOptions;
@@ -93,56 +78,9 @@
   /// results have been invalidated.
   void set analysisOptions(AnalysisOptions options);
 
-  /// Set the order in which sources will be analyzed by [performAnalysisTask] to
-  /// match the order of the sources in the given list of [sources]. If a source
-  /// that needs to be analyzed is not contained in the list, then it will be
-  /// treated as if it were at the end of the list. If the list is empty (or
-  /// `null`) then no sources will be given priority over other sources.
-  ///
-  /// Changes made to the list after this method returns will <b>not</b> be
-  /// reflected in the priority order.
-  void set analysisPriorityOrder(List<Source> sources);
-
   /// Return the set of declared variables used when computing constant values.
   DeclaredVariables get declaredVariables;
 
-  /// Return a list containing all of the sources known to this context that
-  /// represent HTML files. The contents of the list can be incomplete.
-  List<Source> get htmlSources;
-
-  /// The stream that is notified when a source either starts or stops being
-  /// analyzed implicitly.
-  Stream<ImplicitAnalysisEvent> get implicitAnalysisEvents;
-
-  /// Returns `true` if this context was disposed using [dispose].
-  bool get isDisposed;
-
-  /// Return a list containing all of the sources known to this context that
-  /// represent the defining compilation unit of a library that can be run within
-  /// a browser. The sources that are returned represent libraries that have a
-  /// 'main' method and are either referenced by an HTML file or import, directly
-  /// or indirectly, a client-only library. The contents of the list can be
-  /// incomplete.
-  List<Source> get launchableClientLibrarySources;
-
-  /// Return a list containing all of the sources known to this context that
-  /// represent the defining compilation unit of a library that can be run
-  /// outside of a browser. The contents of the list can be incomplete.
-  List<Source> get launchableServerLibrarySources;
-
-  /// Return a list containing all of the sources known to this context that
-  /// represent the defining compilation unit of a library. The contents of the
-  /// list can be incomplete.
-  List<Source> get librarySources;
-
-  /// Return a client-provided name used to identify this context, or `null` if
-  /// the client has not provided a name.
-  String get name;
-
-  /// Set the client-provided name used to identify this context to the given
-  /// [name].
-  set name(String name);
-
   /// Return the source factory used to create the sources that can be analyzed
   /// in this context.
   SourceFactory get sourceFactory;
@@ -152,9 +90,6 @@
   /// all analysis results have been invalidated.
   void set sourceFactory(SourceFactory factory);
 
-  /// Return a list containing all of the sources known to this context.
-  List<Source> get sources;
-
   /// Return a type provider for this context or throw [AnalysisException] if
   /// either `dart:core` or `dart:async` cannot be resolved.
   TypeProvider get typeProvider;
@@ -162,364 +97,11 @@
   /// Return a type system for this context.
   TypeSystem get typeSystem;
 
-  /// Add the given [listener] to the list of objects that are to be notified
-  /// when various analysis results are produced in this context.
-  void addListener(AnalysisListener listener);
-
-  /// Apply the given [delta] to change the level of analysis that will be
-  /// performed for the sources known to this context.
-  void applyAnalysisDelta(AnalysisDelta delta);
-
   /// Apply the changes specified by the given [changeSet] to this context. Any
   /// analysis results that have been invalidated by these changes will be
   /// removed.
+  /// TODO(scheglov) This method is referenced by the internal indexer tool.
   void applyChanges(ChangeSet changeSet);
-
-  /// Return the documentation comment for the given [element] as it appears in
-  /// the original source (complete with the beginning and ending delimiters) for
-  /// block documentation comments, or lines starting with `"///"` and separated
-  /// with `"\n"` characters for end-of-line documentation comments, or `null` if
-  /// the 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 an [AnalysisException] if the documentation comment could not be
-  /// determined because the analysis could not be performed.
-  ///
-  /// <b>Note:</b> This method cannot be used in an async environment.
-  String computeDocumentationComment(Element element);
-
-  /// Return a list containing all of the errors associated with the given
-  /// [source]. If the errors are not already known then the source will be
-  /// analyzed in order to determine the errors associated with it.
-  ///
-  /// Throws an [AnalysisException] if the errors could not be determined because
-  /// the analysis could not be performed.
-  ///
-  /// <b>Note:</b> This method cannot be used in an async environment.
-  ///
-  /// See [getErrors].
-  List<AnalysisError> computeErrors(Source source);
-
-  /// Return the kind of the given [source], computing it's kind if it is not
-  /// already known. Return [SourceKind.UNKNOWN] if the source is not contained
-  /// in this context.
-  ///
-  /// <b>Note:</b> This method cannot be used in an async environment.
-  ///
-  /// See [getKindOf].
-  SourceKind computeKindOf(Source source);
-
-  /// Return the element model corresponding to the library defined by the given
-  /// [source]. If the element model does not yet exist it will be created. The
-  /// process of creating an element model for a library can long-running,
-  /// depending on the size of the library and the number of libraries that are
-  /// imported into it that also need to have a model built for them.
-  ///
-  /// Throws an [AnalysisException] if the element model could not be determined
-  /// because the analysis could not be performed.
-  ///
-  /// <b>Note:</b> This method cannot be used in an async environment.
-  ///
-  /// See [getLibraryElement].
-  LibraryElement computeLibraryElement(Source source);
-
-  /// Return the line information for the given [source], or `null` if the source
-  /// is not of a recognized kind (neither a Dart nor HTML file). If the line
-  /// information was not previously known it will be created. The line
-  /// information is used to map offsets from the beginning of the source to line
-  /// and column pairs.
-  ///
-  /// Throws an [AnalysisException] if the line information could not be
-  /// determined because the analysis could not be performed.
-  ///
-  /// <b>Note:</b> This method cannot be used in an async environment.
-  ///
-  /// See [getLineInfo].
-  LineInfo computeLineInfo(Source source);
-
-  /// Return a future which will be completed with the fully resolved AST for a
-  /// single compilation unit within the given library, once that AST is up to
-  /// date.
-  ///
-  /// If the resolved AST can't be computed for some reason, the future will be
-  /// completed with an error.  One possible error is AnalysisNotScheduledError,
-  /// which means that the resolved AST can't be computed because the given
-  /// source file is not scheduled to be analyzed within the context of the
-  /// given library.
-  CancelableFuture<CompilationUnit> computeResolvedCompilationUnitAsync(
-      Source source, Source librarySource);
-
-  /// Notifies the context that the client is going to stop using this context.
-  void dispose();
-
-  /// Return `true` if the given [source] exists.
-  ///
-  /// This method should be used rather than the method [Source.exists] because
-  /// contexts can have local overrides of the content of a source that the
-  /// source is not aware of and a source with local content is considered to
-  /// exist even if there is no file on disk.
-  bool exists(Source source);
-
-  /// Return the element model corresponding to the compilation unit defined by
-  /// the given [unitSource] in the library defined by the given [librarySource],
-  /// or `null` if the element model does not currently exist or if the library
-  /// cannot be analyzed for some reason.
-  CompilationUnitElement getCompilationUnitElement(
-      Source unitSource, Source librarySource);
-
-  /// Return the contents and timestamp of the given [source].
-  ///
-  /// This method should be used rather than the method [Source.getContents]
-  /// because contexts can have local overrides of the content of a source that
-  /// the source is not aware of.
-  TimestampedData<String> getContents(Source source);
-
-  /// Return the element referenced by the given [location], or `null` if the
-  /// element is not immediately available or if there is no element with the
-  /// given location. The latter condition can occur, for example, if the
-  /// location describes an element from a different context or if the element
-  /// has been removed from this context as a result of some change since it was
-  /// originally obtained.
-  Element getElement(ElementLocation location);
-
-  /// Return an analysis error info containing the list of all of the errors and
-  /// the line info associated with the given [source]. The list of errors will
-  /// be empty if the source is not known to this context or if there are no
-  /// errors in the source. The errors contained in the list can be incomplete.
-  ///
-  /// See [computeErrors].
-  AnalysisErrorInfo getErrors(Source source);
-
-  /// Return the sources for the HTML files that reference the compilation unit
-  /// with the given [source]. If the source does not represent a Dart source or
-  /// is not known to this context, the returned list will be empty. The contents
-  /// of the list can be incomplete.
-  List<Source> getHtmlFilesReferencing(Source source);
-
-  /// Return the kind of the given [source], or `null` if the kind is not known
-  /// to this context.
-  ///
-  /// See [computeKindOf].
-  SourceKind getKindOf(Source source);
-
-  /// Return the sources for the defining compilation units of any libraries of
-  /// which the given [source] is a part. The list will normally contain a single
-  /// library because most Dart sources are only included in a single library,
-  /// but it is possible to have a part that is contained in multiple identically
-  /// named libraries. If the source represents the defining compilation unit of
-  /// a library, then the returned list will contain the given source as its only
-  /// element. If the source does not represent a Dart source or is not known to
-  /// this context, the returned list will be empty. The contents of the list can
-  /// be incomplete.
-  List<Source> getLibrariesContaining(Source source);
-
-  /// Return the sources for the defining compilation units of any libraries that
-  /// depend on the library defined by the given [librarySource]. One library
-  /// depends on another if it either imports or exports that library.
-  List<Source> getLibrariesDependingOn(Source librarySource);
-
-  /// Return the sources for the defining compilation units of any libraries that
-  /// are referenced from the HTML file defined by the given [htmlSource].
-  List<Source> getLibrariesReferencedFromHtml(Source htmlSource);
-
-  /// Return the element model corresponding to the library defined by the given
-  /// [source], or `null` if the element model does not currently exist or if the
-  /// library cannot be analyzed for some reason.
-  LibraryElement getLibraryElement(Source source);
-
-  /// Return the line information for the given [source], or `null` if the line
-  /// information is not known. The line information is used to map offsets from
-  /// the beginning of the source to line and column pairs.
-  ///
-  /// See [computeLineInfo].
-  LineInfo getLineInfo(Source source);
-
-  /// Return the modification stamp for the [source], or a negative value if the
-  /// source does not exist. A modification stamp is a non-negative integer with
-  /// the property that if the contents of the source have not been modified
-  /// since the last time the modification stamp was accessed then the same value
-  /// will be returned, but if the contents of the source have been modified one
-  /// or more times (even if the net change is zero) the stamps will be different.
-  ///
-  /// This method should be used rather than the method
-  /// [Source.getModificationStamp] because contexts can have local overrides of
-  /// the content of a source that the source is not aware of.
-  int getModificationStamp(Source source);
-
-  /// Return a fully resolved AST for the compilation unit defined by the given
-  /// [unitSource] within the given [library], or `null` if the resolved AST is
-  /// not already computed.
-  ///
-  /// See [resolveCompilationUnit].
-  CompilationUnit getResolvedCompilationUnit(
-      Source unitSource, LibraryElement library);
-
-  /// Return a fully resolved AST for the compilation unit defined by the given
-  /// [unitSource] within the library defined by the given [librarySource], or
-  /// `null` if the resolved AST is not already computed.
-  ///
-  /// See [resolveCompilationUnit2].
-  CompilationUnit getResolvedCompilationUnit2(
-      Source unitSource, Source librarySource);
-
-  /// Return a list of the sources being analyzed in this context whose full path
-  /// is equal to the given [path].
-  List<Source> getSourcesWithFullName(String path);
-
-  /// Invalidates hints in the given [librarySource] and included parts.
-  void invalidateLibraryHints(Source librarySource);
-
-  /// Return `true` if the given [librarySource] is known to be the defining
-  /// compilation unit of a library that can be run on a client (references
-  /// 'dart:html', either directly or indirectly).
-  ///
-  /// <b>Note:</b> In addition to the expected case of returning `false` if the
-  /// source is known to be a library that cannot be run on a client, this method
-  /// will also return `false` if the source is not known to be a library or if
-  /// we do not know whether it can be run on a client.
-  bool isClientLibrary(Source librarySource);
-
-  /// Return `true` if the given [librarySource] is known to be the defining
-  /// compilation unit of a library that can be run on the server (does not
-  /// reference 'dart:html', either directly or indirectly).
-  ///
-  /// <b>Note:</b> In addition to the expected case of returning `false` if the
-  /// source is known to be a library that cannot be run on the server, this
-  /// method will also return `false` if the source is not known to be a library
-  /// or if we do not know whether it can be run on the server.
-  bool isServerLibrary(Source librarySource);
-
-  /// Parse the content of the given [source] to produce an AST structure. The
-  /// resulting AST structure may or may not be resolved, and may have a slightly
-  /// different structure depending upon whether it is resolved.
-  ///
-  /// Throws an [AnalysisException] if the analysis could not be performed
-  ///
-  /// <b>Note:</b> This method cannot be used in an async environment.
-  CompilationUnit parseCompilationUnit(Source source);
-
-  /// Perform the next unit of work required to keep the analysis results
-  /// up-to-date and return information about the consequent changes to the
-  /// analysis results. This method can be long running.
-  ///
-  /// The implementation that uses the task model notifies subscribers of
-  /// [onResultChanged] about computed results.
-  ///
-  /// The following results are computed for Dart sources.
-  ///
-  /// 1. For explicit and implicit sources:
-  ///    [PARSED_UNIT]
-  ///    [RESOLVED_UNIT]
-  ///
-  /// 2. For explicit sources:
-  ///    [DART_ERRORS].
-  ///
-  /// 3. For explicit and implicit library sources:
-  ///    [LIBRARY_ELEMENT].
-  AnalysisResult performAnalysisTask();
-
-  /// Remove the given [listener] from the list of objects that are to be
-  /// notified when various analysis results are produced in this context.
-  void removeListener(AnalysisListener listener);
-
-  /// Return a fully resolved AST for the compilation unit defined by the given
-  /// [unitSource] within the given [library].
-  ///
-  /// Throws an [AnalysisException] if the analysis could not be performed.
-  ///
-  /// <b>Note:</b> This method cannot be used in an async environment.
-  ///
-  /// See [getResolvedCompilationUnit].
-  CompilationUnit resolveCompilationUnit(
-      Source unitSource, LibraryElement library);
-
-  /// Return a fully resolved AST for the compilation unit defined by the given
-  /// [unitSource] within the library defined by the given [librarySource].
-  ///
-  /// Throws an [AnalysisException] if the analysis could not be performed.
-  ///
-  /// <b>Note:</b> This method cannot be used in an async environment.
-  ///
-  /// See [getResolvedCompilationUnit2].
-  CompilationUnit resolveCompilationUnit2(
-      Source unitSource, Source librarySource);
-
-  /// Set the contents of the given [source] to the given [contents] and mark the
-  /// source as having changed. The additional [offset] and [length] information
-  /// is used by the context to determine what reanalysis is necessary.
-  void setChangedContents(
-      Source source, String contents, int offset, int oldLength, int newLength);
-
-  /// Set the contents of the given [source] to the given [contents] and mark the
-  /// source as having changed. This has the effect of overriding the default
-  /// contents of the source. If the contents are `null` the override is removed
-  /// so that the default contents will be returned.
-  void setContents(Source source, String contents);
-}
-
-/// A representation of changes to the types of analysis that should be
-/// performed.
-class AnalysisDelta {
-  /// A mapping from source to what type of analysis should be performed on that
-  /// source.
-  Map<Source, AnalysisLevel> _analysisMap =
-      new HashMap<Source, AnalysisLevel>();
-
-  /// Return a collection of the sources that have been added. This is equivalent
-  /// to calling [getAnalysisLevels] and collecting all sources that do not have
-  /// an analysis level of [AnalysisLevel.NONE].
-  List<Source> get addedSources {
-    List<Source> result = new List<Source>();
-    _analysisMap.forEach((Source source, AnalysisLevel level) {
-      if (level != AnalysisLevel.NONE) {
-        result.add(source);
-      }
-    });
-    return result;
-  }
-
-  /// Return a mapping of sources to the level of analysis that should be
-  /// performed.
-  Map<Source, AnalysisLevel> get analysisLevels => _analysisMap;
-
-  /// Record that the given [source] should be analyzed at the given [level].
-  void setAnalysisLevel(Source source, AnalysisLevel level) {
-    _analysisMap[source] = level;
-  }
-
-  @override
-  String toString() {
-    StringBuffer buffer = new StringBuffer();
-    bool needsSeparator = _appendSources(buffer, false, AnalysisLevel.ALL);
-    needsSeparator =
-        _appendSources(buffer, needsSeparator, AnalysisLevel.RESOLVED);
-    _appendSources(buffer, needsSeparator, AnalysisLevel.NONE);
-    return buffer.toString();
-  }
-
-  /// Append to the given [buffer] all sources with the given analysis [level],
-  /// prefixed with a label and a separator if [needsSeparator] is `true`.
-  bool _appendSources(
-      StringBuffer buffer, bool needsSeparator, AnalysisLevel level) {
-    bool first = true;
-    _analysisMap.forEach((Source source, AnalysisLevel sourceLevel) {
-      if (sourceLevel == level) {
-        if (first) {
-          first = false;
-          if (needsSeparator) {
-            buffer.write("; ");
-          }
-          buffer.write(level);
-          buffer.write(" ");
-        } else {
-          buffer.write(", ");
-        }
-        buffer.write(source.fullName);
-      }
-    });
-    return needsSeparator || !first;
-  }
 }
 
 /// The entry point for the functionality provided by the analysis engine. There
@@ -662,79 +244,6 @@
   AnalysisErrorInfoImpl(this.errors, this.lineInfo);
 }
 
-/// The levels at which a source can be analyzed.
-class AnalysisLevel implements Comparable<AnalysisLevel> {
-  /// Indicates a source should be fully analyzed.
-  static const AnalysisLevel ALL = const AnalysisLevel('ALL', 0);
-
-  /// Indicates a source should be resolved and that errors, warnings and hints
-  /// are needed.
-  static const AnalysisLevel ERRORS = const AnalysisLevel('ERRORS', 1);
-
-  /// Indicates a source should be resolved, but that errors, warnings and hints
-  /// are not needed.
-  static const AnalysisLevel RESOLVED = const AnalysisLevel('RESOLVED', 2);
-
-  /// Indicates a source is not of interest to the client.
-  static const AnalysisLevel NONE = const AnalysisLevel('NONE', 3);
-
-  static const List<AnalysisLevel> values = const [ALL, ERRORS, RESOLVED, NONE];
-
-  /// The name of this analysis level.
-  final String name;
-
-  /// The ordinal value of the analysis level.
-  final int ordinal;
-
-  const AnalysisLevel(this.name, this.ordinal);
-
-  @override
-  int get hashCode => ordinal;
-
-  @override
-  int compareTo(AnalysisLevel other) => ordinal - other.ordinal;
-
-  @override
-  String toString() => name;
-}
-
-/// An object that is listening for results being produced by an analysis
-/// context.
-abstract class AnalysisListener {
-  /// Reports that a task, described by the given [taskDescription] is about to
-  /// be performed by the given [context].
-  void aboutToPerformTask(AnalysisContext context, String taskDescription);
-
-  /// Reports that the [errors] associated with the given [source] in the given
-  /// [context] has been updated to the given errors. The [lineInfo] is the line
-  /// information associated with the source.
-  void computedErrors(AnalysisContext context, Source source,
-      List<AnalysisError> errors, LineInfo lineInfo);
-
-  /// Reports that the given [source] is no longer included in the set of sources
-  /// that are being analyzed by the given analysis [context].
-  void excludedSource(AnalysisContext context, Source source);
-
-  /// Reports that the given [source] is now included in the set of sources that
-  /// are being analyzed by the given analysis [context].
-  void includedSource(AnalysisContext context, Source source);
-
-  /// Reports that the given Dart [source] was parsed in the given [context],
-  /// producing the given [unit].
-  void parsedDart(AnalysisContext context, Source source, CompilationUnit unit);
-
-  /// Reports that the given Dart [source] was resolved in the given [context].
-  void resolvedDart(
-      AnalysisContext context, Source source, CompilationUnit unit);
-}
-
-/// Futures returned by [AnalysisContext] for pending analysis results will
-/// complete with this error if it is determined that analysis results will
-/// never become available (e.g. because the requested source is not subject to
-/// analysis, or because the requested source is a part file which is not a part
-/// of any known library).
-class AnalysisNotScheduledError implements Exception {}
-
 /// A set of analysis options used to control the behavior of an analysis
 /// context.
 abstract class AnalysisOptions {
@@ -1366,213 +875,6 @@
   static bool _analyzeNoFunctionBodies(Source _) => false;
 }
 
-///
-class AnalysisResult {
-  /// The change notices associated with this result, or `null` if there were no
-  /// changes and there is no more work to be done.
-  final List<ChangeNotice> _notices;
-
-  /// The number of milliseconds required to determine which task was to be
-  /// performed.
-  final int getTime;
-
-  /// The name of the class of the task that was performed.
-  final String taskClassName;
-
-  /// The number of milliseconds required to perform the task.
-  final int performTime;
-
-  /// Initialize a newly created analysis result to have the given values. The
-  /// [notices] is the change notices associated with this result. The [getTime]
-  /// is the number of milliseconds required to determine which task was to be
-  /// performed. The [taskClassName] is the name of the class of the task that
-  /// was performed. The [performTime] is the number of milliseconds required to
-  /// perform the task.
-  AnalysisResult(
-      this._notices, this.getTime, this.taskClassName, this.performTime);
-
-  /// Return the change notices associated with this result, or `null` if there
-  /// were no changes and there is no more work to be done.
-  List<ChangeNotice> get changeNotices => _notices;
-
-  /// Return `true` if there is more to be performed after the task that was
-  /// performed.
-  bool get hasMoreWork => _notices != null;
-}
-
-/// Statistics about cache consistency validation.
-class CacheConsistencyValidationStatistics {
-  /// Number of sources which were changed, but the context was not notified
-  /// about it, so this fact was detected only during cache consistency
-  /// validation.
-  int numOfChanged = 0;
-
-  /// Number of sources which stopped existing, but the context was not notified
-  /// about it, so this fact was detected only during cache consistency
-  /// validation.
-  int numOfRemoved = 0;
-
-  /// Reset all counters.
-  void reset() {
-    numOfChanged = 0;
-    numOfRemoved = 0;
-  }
-}
-
-/// Interface for cache consistency validation in an [InternalAnalysisContext].
-abstract class CacheConsistencyValidator {
-  /// Return sources for which the contexts needs to know modification times.
-  List<Source> getSourcesToComputeModificationTimes();
-
-  /// Notify the validator that modification [times] were computed for [sources].
-  /// If a source does not exist, its modification time is `-1`.
-  ///
-  /// It's up to the validator and the context how to use this information,
-  /// the list of sources the context has might have been changed since the
-  /// previous invocation of [getSourcesToComputeModificationTimes].
-  ///
-  /// Check the cache for any invalid entries (entries whose modification time
-  /// does not match the modification time of the source associated with the
-  /// entry). Invalid entries will be marked as invalid so that the source will
-  /// be re-analyzed. Return `true` if at least one entry was invalid.
-  bool sourceModificationTimesComputed(List<Source> sources, List<int> times);
-}
-
-/// The possible states of cached data.
-class CacheState implements Comparable<CacheState> {
-  /// The data is not in the cache and the last time an attempt was made to
-  /// compute the data an exception occurred, making it pointless to attempt to
-  /// compute the data again.
-  ///
-  /// Valid Transitions:
-  /// * [INVALID] if a source was modified that might cause the data to be
-  ///   computable
-  static const CacheState ERROR = const CacheState('ERROR', 0);
-
-  /// The data is not in the cache because it was flushed from the cache in order
-  /// to control memory usage. If the data is recomputed, results do not need to
-  /// be reported.
-  ///
-  /// Valid Transitions:
-  /// * [IN_PROCESS] if the data is being recomputed
-  /// * [INVALID] if a source was modified that causes the data to need to be
-  ///   recomputed
-  static const CacheState FLUSHED = const CacheState('FLUSHED', 1);
-
-  /// The data might or might not be in the cache but is in the process of being
-  /// recomputed.
-  ///
-  /// Valid Transitions:
-  /// * [ERROR] if an exception occurred while trying to compute the data
-  /// * [VALID] if the data was successfully computed and stored in the cache
-  static const CacheState IN_PROCESS = const CacheState('IN_PROCESS', 2);
-
-  /// The data is not in the cache and needs to be recomputed so that results can
-  /// be reported.
-  ///
-  /// Valid Transitions:
-  /// * [IN_PROCESS] if an attempt is being made to recompute the data
-  static const CacheState INVALID = const CacheState('INVALID', 3);
-
-  /// The data is in the cache and up-to-date.
-  ///
-  /// Valid Transitions:
-  /// * [FLUSHED] if the data is removed in order to manage memory usage
-  /// * [INVALID] if a source was modified in such a way as to invalidate the
-  ///   previous data
-  static const CacheState VALID = const CacheState('VALID', 4);
-
-  static const List<CacheState> values = const [
-    ERROR,
-    FLUSHED,
-    IN_PROCESS,
-    INVALID,
-    VALID
-  ];
-
-  /// The name of this cache state.
-  final String name;
-
-  /// The ordinal value of the cache state.
-  final int ordinal;
-
-  const CacheState(this.name, this.ordinal);
-
-  @override
-  int get hashCode => ordinal;
-
-  @override
-  int compareTo(CacheState other) => ordinal - other.ordinal;
-
-  @override
-  String toString() => name;
-}
-
-/// An object that represents a change to the analysis results associated with a
-/// given source.
-abstract class ChangeNotice implements AnalysisErrorInfo {
-  /// The parsed, but maybe not resolved Dart AST that changed as a result of
-  /// the analysis, or `null` if the AST was not changed.
-  CompilationUnit get parsedDartUnit;
-
-  /// The fully resolved Dart AST that changed as a result of the analysis, or
-  /// `null` if the AST was not changed.
-  CompilationUnit get resolvedDartUnit;
-
-  /// Return the source for which the result is being reported.
-  Source get source;
-}
-
-/// An implementation of a [ChangeNotice].
-class ChangeNoticeImpl implements ChangeNotice {
-  /// The source for which the result is being reported.
-  @override
-  final Source source;
-
-  /// The parsed, but maybe not resolved Dart AST that changed as a result of
-  /// the analysis, or `null` if the AST was not changed.
-  @override
-  CompilationUnit parsedDartUnit;
-
-  /// The fully resolved Dart AST that changed as a result of the analysis, or
-  /// `null` if the AST was not changed.
-  @override
-  CompilationUnit resolvedDartUnit;
-
-  /// The errors that changed as a result of the analysis, or `null` if errors
-  /// were not changed.
-  List<AnalysisError> _errors;
-
-  /// The line information associated with the source, or `null` if errors were
-  /// not changed.
-  LineInfo _lineInfo;
-
-  /// Initialize a newly created notice associated with the given source.
-  ///
-  /// @param source the source for which the change is being reported
-  ChangeNoticeImpl(this.source);
-
-  @override
-  List<AnalysisError> get errors => _errors;
-
-  @override
-  LineInfo get lineInfo => _lineInfo;
-
-  /// Set the errors that changed as a result of the analysis to the given
-  /// [errors] and set the line information to the given [lineInfo].
-  void setErrors(List<AnalysisError> errors, LineInfo lineInfo) {
-    this._errors = errors;
-    this._lineInfo = lineInfo;
-    if (lineInfo == null) {
-      AnalysisEngine.instance.logger.logInformation("No line info: $source",
-          new CaughtException(new AnalysisException(), null));
-    }
-  }
-
-  @override
-  String toString() => "Changes for ${source.fullName}";
-}
-
 /// An indication of which sources have been added, changed, removed, or deleted.
 /// In the case of a changed source, there are multiple ways of indicating the
 /// nature of the change.
@@ -1760,131 +1062,11 @@
       this.contents, this.offset, this.oldLength, this.newLength);
 }
 
-/// An event indicating when a source either starts or stops being implicitly
-/// analyzed.
-class ImplicitAnalysisEvent {
-  /// The source whose status has changed.
-  final Source source;
-
-  /// A flag indicating whether the source is now being analyzed.
-  final bool isAnalyzed;
-
-  /// Initialize a newly created event to indicate that the given [source] has
-  /// changed it status to match the [isAnalyzed] flag.
-  ImplicitAnalysisEvent(this.source, this.isAnalyzed);
-
-  @override
-  String toString() =>
-      '${isAnalyzed ? '' : 'not '}analyzing ${source.fullName}';
-}
-
 /// Additional behavior for an analysis context that is required by internal
 /// users of the context.
 abstract class InternalAnalysisContext implements AnalysisContext {
-  /// A table mapping the sources known to the context to the information known
-  /// about the source.
-  AnalysisCache get analysisCache;
-
-  /// The cache consistency validator for this context.
-  CacheConsistencyValidator get cacheConsistencyValidator;
-
-  /// Allow the client to supply its own content cache.  This will take the
-  /// place of the content cache created by default, allowing clients to share
-  /// the content cache between contexts.
-  set contentCache(ContentCache value);
-
-  /// Get the [EmbedderYamlLocator] for this context.
-  @deprecated
-  EmbedderYamlLocator get embedderYamlLocator;
-
-  /// Return a list of the explicit targets being analyzed by this context.
-  List<AnalysisTarget> get explicitTargets;
-
-  /// Return `true` if the context is active, i.e. is being analyzed now.
-  bool get isActive;
-
-  /// Specify whether the context is active, i.e. is being analyzed now.
-  set isActive(bool value);
-
-  /// Return a list containing all of the sources that have been marked as
-  /// priority sources. Clients must not modify the returned list.
-  List<Source> get prioritySources;
-
-  /// Return a list of the priority targets being analyzed by this context.
-  List<AnalysisTarget> get priorityTargets;
-
-  /// The partition that contains analysis results that are not shared with other
-  /// contexts.
-  CachePartition get privateAnalysisCachePartition;
-
   /// Sets the [TypeProvider] for this context.
   void set typeProvider(TypeProvider typeProvider);
-
-  /// Return a list containing the sources of the libraries that are exported by
-  /// the library with the given [source]. The list will be empty if the given
-  /// source is invalid, if the given source does not represent a library, or if
-  /// the library does not export any other libraries.
-  ///
-  /// Throws an [AnalysisException] if the exported libraries could not be
-  /// computed.
-  List<Source> computeExportedLibraries(Source source);
-
-  /// Return a list containing the sources of the libraries that are imported by
-  /// the library with the given [source]. The list will be empty if the given
-  /// source is invalid, if the given source does not represent a library, or if
-  /// the library does not import any other libraries.
-  ///
-  /// Throws an [AnalysisException] if the imported libraries could not be
-  /// computed.
-  List<Source> computeImportedLibraries(Source source);
-
-  /// Return all the resolved [CompilationUnit]s for the given [source] if not
-  /// flushed, otherwise return `null` and ensures that the [CompilationUnit]s
-  /// will be eventually returned to the client from [performAnalysisTask].
-  List<CompilationUnit> ensureResolvedDartUnits(Source source);
-
-  /// Return context that owns the given [source].
-  InternalAnalysisContext getContextFor(Source source);
-
-  /// Return a change notice for the given [source], creating one if one does not
-  /// already exist.
-  ChangeNoticeImpl getNotice(Source source);
-
-  /// Return a namespace containing mappings for all of the public names defined
-  /// by the given [library].
-  Namespace getPublicNamespace(LibraryElement library);
-
-  /// Respond to a change which has been made to the given [source] file.
-  /// [originalContents] is the former contents of the file, and [newContents]
-  /// is the updated contents.  If [notify] is true, a source changed event is
-  /// triggered.
-  ///
-  /// Normally it should not be necessary for clients to call this function,
-  /// since it will be automatically invoked in response to a call to
-  /// [applyChanges] or [setContents].  However, if this analysis context is
-  /// sharing its content cache with other contexts, then the client must
-  /// manually update the content cache and call this function for each context.
-  ///
-  /// Return `true` if the change was significant to this context (i.e. [source]
-  /// is either implicitly or explicitly analyzed by this context, and a change
-  /// actually occurred).
-  bool handleContentsChanged(
-      Source source, String originalContents, String newContents, bool notify);
-
-  /// Given an [elementMap] mapping the source for the libraries represented by
-  /// the corresponding elements to the elements representing the libraries,
-  /// record those mappings.
-  void recordLibraryElements(Map<Source, LibraryElement> elementMap);
-
-  /// Return `true` if errors should be produced for the given [source].
-  bool shouldErrorsBeAnalyzed(Source source);
-
-  /// For testing only: flush all representations of the AST (both resolved and
-  /// unresolved) for the given [source] out of the cache.
-  void test_flushAstStructures(Source source);
-
-  /// Visit all entries of the content cache.
-  void visitContentCache(ContentCacheVisitor visitor);
 }
 
 /// An object that can be used to receive information about errors within the
@@ -1916,25 +1098,6 @@
   void logInformation(String message, [CaughtException exception]) {}
 }
 
-/// An exception created when an analysis attempt fails because a source was
-/// deleted between the time the analysis started and the time the results of the
-/// analysis were ready to be recorded.
-class ObsoleteSourceAnalysisException extends AnalysisException {
-  /// The source that was removed while it was being analyzed.
-  Source _source;
-
-  /// Initialize a newly created exception to represent the removal of the given
-  /// [source].
-  ObsoleteSourceAnalysisException(Source source)
-      : super(
-            "The source '${source.fullName}' was removed while it was being analyzed") {
-    this._source = source;
-  }
-
-  /// Return the source that was removed while it was being analyzed.
-  Source get source => _source;
-}
-
 /// Container with global [AnalysisContext] performance statistics.
 class PerformanceStatistics {
   /// The [PerformanceTag] for `package:analyzer`.
@@ -1969,143 +1132,4 @@
 
   /// The [PerformanceTag] for time spent in summaries support.
   static PerformanceTag summary = analyzer.createChild('summary');
-
-  /// Statistics about cache consistency validation.
-  static final CacheConsistencyValidationStatistics
-      cacheConsistencyValidationStatistics =
-      new CacheConsistencyValidationStatistics();
-}
-
-/// An visitor that removes any resolution information from an AST structure when
-/// used to visit that structure.
-class ResolutionEraser extends GeneralizingAstVisitor<void> {
-  /// A flag indicating whether the elements associated with declarations should
-  /// be erased.
-  bool eraseDeclarations = true;
-
-  @override
-  void visitAssignmentExpression(AssignmentExpression node) {
-    node.staticElement = null;
-    super.visitAssignmentExpression(node);
-  }
-
-  @override
-  void visitBinaryExpression(BinaryExpression node) {
-    node.staticElement = null;
-    super.visitBinaryExpression(node);
-  }
-
-  @override
-  void visitBreakStatement(BreakStatement node) {
-    node.target = null;
-    super.visitBreakStatement(node);
-  }
-
-  @override
-  void visitCompilationUnit(CompilationUnit node) {
-    if (eraseDeclarations) {
-      node.element = null;
-    }
-    super.visitCompilationUnit(node);
-  }
-
-  @override
-  void visitConstructorDeclaration(ConstructorDeclaration node) {
-    if (eraseDeclarations) {
-      (node as ConstructorDeclarationImpl).declaredElement = null;
-    }
-    super.visitConstructorDeclaration(node);
-  }
-
-  @override
-  void visitConstructorName(ConstructorName node) {
-    node.staticElement = null;
-    super.visitConstructorName(node);
-  }
-
-  @override
-  void visitContinueStatement(ContinueStatement node) {
-    node.target = null;
-    super.visitContinueStatement(node);
-  }
-
-  @override
-  void visitDirective(Directive node) {
-    if (eraseDeclarations) {
-      node.element = null;
-    }
-    super.visitDirective(node);
-  }
-
-  @override
-  void visitExpression(Expression node) {
-    node.staticType = null;
-    super.visitExpression(node);
-  }
-
-  @override
-  void visitFunctionExpression(FunctionExpression node) {
-    if (eraseDeclarations) {
-      (node as FunctionExpressionImpl).declaredElement = null;
-    }
-    super.visitFunctionExpression(node);
-  }
-
-  @override
-  void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
-    node.staticElement = null;
-    super.visitFunctionExpressionInvocation(node);
-  }
-
-  @override
-  void visitIndexExpression(IndexExpression node) {
-    node.staticElement = null;
-    super.visitIndexExpression(node);
-  }
-
-  @override
-  void visitInstanceCreationExpression(InstanceCreationExpression node) {
-    node.staticElement = null;
-    super.visitInstanceCreationExpression(node);
-  }
-
-  @override
-  void visitPostfixExpression(PostfixExpression node) {
-    node.staticElement = null;
-    super.visitPostfixExpression(node);
-  }
-
-  @override
-  void visitPrefixExpression(PrefixExpression node) {
-    node.staticElement = null;
-    super.visitPrefixExpression(node);
-  }
-
-  @override
-  void visitRedirectingConstructorInvocation(
-      RedirectingConstructorInvocation node) {
-    node.staticElement = null;
-    super.visitRedirectingConstructorInvocation(node);
-  }
-
-  @override
-  void visitSimpleIdentifier(SimpleIdentifier node) {
-    if (eraseDeclarations || !node.inDeclarationContext()) {
-      node.staticElement = null;
-    }
-    super.visitSimpleIdentifier(node);
-  }
-
-  @override
-  void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
-    node.staticElement = null;
-    super.visitSuperConstructorInvocation(node);
-  }
-
-  /// Remove any resolution information from the given AST structure.
-  static void erase(AstNode node, {bool eraseDeclarations: true}) {
-    ResolutionEraser eraser = new ResolutionEraser();
-    eraser.eraseDeclarations = eraseDeclarations;
-    node.accept(eraser);
-  }
 }
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 3b1fd26..566e931 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -996,8 +996,7 @@
   @override
   void visitIndexExpression(IndexExpression node) {
     _checkForArgumentTypeNotAssignableForArgument(node.index);
-    if (node.leftBracket.type !=
-        TokenType.QUESTION_PERIOD_OPEN_SQUARE_BRACKET) {
+    if (!node.isNullAware) {
       _checkForNullableDereference(node.target);
     }
     super.visitIndexExpression(node);
@@ -1106,7 +1105,7 @@
     _typeArgumentsVerifier.checkMethodInvocation(node);
     _checkForNullableDereference(methodName);
     _requiredParametersVerifier.visitMethodInvocation(node);
-    if (node.operator?.type != TokenType.QUESTION_PERIOD &&
+    if (!node.isNullAware &&
         methodName.name != 'toString' &&
         methodName.name != 'noSuchMethod') {
       _checkForNullableDereference(target);
@@ -1219,7 +1218,7 @@
     _checkForStaticAccessToInstanceMember(typeReference, propertyName);
     _checkForInstanceAccessToStaticMember(
         typeReference, node.target, propertyName);
-    if (node.operator?.type != TokenType.QUESTION_PERIOD &&
+    if (!node.isNullAware &&
         !_objectPropertyNames.contains(propertyName.name)) {
       _checkForNullableDereference(node.target);
     }
@@ -2245,7 +2244,7 @@
     if (_enclosingClass == null) {
       return;
     }
-    InterfaceType enclosingType = _enclosingClass.type;
+    InterfaceType enclosingType = _enclosingClass.thisType;
     Uri libraryUri = _currentLibrary.source.uri;
 
     // method declared in the enclosing class vs. inherited getter/setter
@@ -2329,7 +2328,7 @@
       visitedClasses.removeLast();
     }
 
-    visit(_enclosingClass.type);
+    visit(_enclosingClass.thisType);
   }
 
   /**
@@ -2726,9 +2725,6 @@
     } else if (parent is ForElement) {
       awaitKeyword = parent.awaitKeyword;
     }
-    DartType loopType = awaitKeyword != null
-        ? _typeProvider.streamType
-        : _typeProvider.iterableType;
 
     // Use an explicit string instead of [loopType] to remove the "<E>".
     String loopTypeName = awaitKeyword != null ? "Stream" : "Iterable";
@@ -2737,13 +2733,23 @@
     // is assignable to the variable's type.
     // TODO(rnystrom): Move this into mostSpecificTypeArgument()?
     iterableType = iterableType.resolveToBound(_typeProvider.objectType);
-    DartType bestIterableType =
-        _typeSystem.mostSpecificTypeArgument(iterableType, loopType);
+
+    ClassElement sequenceElement = awaitKeyword != null
+        ? _typeProvider.streamElement
+        : _typeProvider.iterableElement;
+
+    DartType bestIterableType;
+    if (iterableType is InterfaceTypeImpl) {
+      var sequenceType = iterableType.asInstanceOf(sequenceElement);
+      if (sequenceType != null) {
+        bestIterableType = sequenceType.typeArguments[0];
+      }
+    }
 
     // Allow it to be a supertype of Iterable<T> (basically just Object) and do
     // an implicit downcast to Iterable<dynamic>.
     if (bestIterableType == null) {
-      if (_typeSystem.isSubtypeOf(loopType, iterableType)) {
+      if (iterableType == _typeProvider.objectType) {
         bestIterableType = DynamicTypeImpl.instance;
       }
     }
@@ -3906,7 +3912,7 @@
       return false;
     }
 
-    InterfaceTypeImpl enclosingType = _enclosingClass.type;
+    InterfaceTypeImpl enclosingType = _enclosingClass.thisType;
     Uri mixinLibraryUri = mixinElement.librarySource.uri;
     for (var name in mixinElementImpl.superInvokedNames) {
       var nameObject = new Name(mixinLibraryUri, name);
@@ -4782,9 +4788,8 @@
       }
     }
     if (!expectedType.isVoid && !fromType.isVoid) {
-      var checkWithType = (!_inAsync)
-          ? fromType
-          : _typeProvider.futureType.instantiate(<DartType>[fromType]);
+      var checkWithType =
+          !_inAsync ? fromType : _typeProvider.futureType2(fromType);
       if (_typeSystem.isAssignableTo(checkWithType, expectedType,
           featureSet: _featureSet)) {
         return;
@@ -5074,10 +5079,24 @@
     if (element is ExecutableElement && !element.isStatic) {
       return;
     }
-    _errorReporter.reportErrorForNode(
-        StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
-        name,
-        [enclosingElement.name]);
+    if (element is MethodElement) {
+      // Invalid methods are reported in
+      // [MethodInvocationResolver._resolveReceiverNull].
+      return;
+    }
+    if (_enclosingExtension != null) {
+      _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode
+              .UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE,
+          name,
+          [enclosingElement.displayName]);
+    } else {
+      _errorReporter.reportErrorForNode(
+          StaticTypeWarningCode
+              .UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
+          name,
+          [enclosingElement.displayName]);
+    }
   }
 
   /**
@@ -5311,11 +5330,9 @@
     if (isYieldEach) {
       impliedReturnType = staticYieldedType;
     } else if (_enclosingFunction.isAsynchronous) {
-      impliedReturnType =
-          _typeProvider.streamType.instantiate(<DartType>[staticYieldedType]);
+      impliedReturnType = _typeProvider.streamType2(staticYieldedType);
     } else {
-      impliedReturnType =
-          _typeProvider.iterableType.instantiate(<DartType>[staticYieldedType]);
+      impliedReturnType = _typeProvider.iterableType2(staticYieldedType);
     }
     if (!_checkForAssignableExpressionAtType(yieldExpression, impliedReturnType,
         declaredReturnType, StaticTypeWarningCode.YIELD_OF_INVALID_TYPE)) {
@@ -5375,7 +5392,7 @@
       return;
     }
     ClassElement classElement = node.declaredElement;
-    var type = classElement.type;
+    var type = classElement.thisType;
     var supertype = classElement.supertype;
     List<InterfaceType> supertypesForMixinInference = <InterfaceType>[];
     ClassElementImpl.collectAllSupertypes(
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 3f2e838..2f1a57f 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -10,6 +10,7 @@
 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/error/error.dart';
 import 'package:analyzer/error/listener.dart';
@@ -91,6 +92,9 @@
   /// Is `true` if NNBD is enabled for the library being analyzed.
   final bool _isNonNullable;
 
+  /// True if inference failures should be reported, otherwise false.
+  final bool _strictInference;
+
   /// Create a new instance of the [BestPracticesVerifier].
   ///
   /// @param errorReporter the error reporter
@@ -108,6 +112,8 @@
   })  : _nullType = typeProvider.nullType,
         _typeSystem = typeSystem ?? new Dart2TypeSystem(typeProvider),
         _isNonNullable = unit.featureSet.isEnabled(Feature.non_nullable),
+        _strictInference =
+            (analysisOptions as AnalysisOptionsImpl).strictInference,
         _inheritanceManager = inheritanceManager,
         _invalidAccessVerifier =
             new _InvalidAccessVerifier(_errorReporter, _currentLibrary) {
@@ -305,6 +311,11 @@
     try {
       _checkForMissingReturn(
           node.returnType, node.functionExpression.body, element, node);
+
+      // Return types are inferred only on non-recursive local functions.
+      if (node.parent is CompilationUnit) {
+        _checkStrictInferenceReturnType(node.returnType, node, node.name.name);
+      }
       super.visitFunctionDeclaration(node);
     } finally {
       _inDeprecatedMember = wasInDeprecatedMember;
@@ -312,6 +323,13 @@
   }
 
   @override
+  void visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
+    // TODO(srawlins): Check strict-inference return type on recursive
+    // local functions.
+    super.visitFunctionDeclarationStatement(node);
+  }
+
+  @override
   void visitFunctionExpression(FunctionExpression node) {
     if (node.parent is! FunctionDeclaration) {
       _checkForMissingReturn(null, node.body, node.declaredElement, node);
@@ -320,6 +338,13 @@
   }
 
   @override
+  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+    _checkStrictInferenceReturnType(
+        node.returnType, node, node.identifier.name);
+    super.visitFunctionTypedFormalParameter(node);
+  }
+
+  @override
   void visitImportDirective(ImportDirective node) {
     _checkForDeprecatedMemberUse(node.uriElement, node);
     ImportElement importElement = node.element;
@@ -360,6 +385,7 @@
       //checkForOverridingPrivateMember(node);
       _checkForMissingReturn(node.returnType, node.body, element, node);
       _checkForUnnecessaryNoSuchMethod(node);
+      _checkStrictInferenceReturnType(node.returnType, node, node.name.name);
       super.visitMethodDeclaration(node);
     } finally {
       _inDeprecatedMember = wasInDeprecatedMember;
@@ -934,7 +960,7 @@
 
     // CAN_BE_NULL_AFTER_NULL_AWARE
     if (parent is MethodInvocation &&
-        parent.operator.type != TokenType.QUESTION_PERIOD &&
+        !parent.isNullAware &&
         _nullType.lookUpMethod(parent.methodName.name, _currentLibrary) ==
             null) {
       _errorReporter.reportErrorForNode(
@@ -942,7 +968,7 @@
       return;
     }
     if (parent is PropertyAccess &&
-        parent.operator.type != TokenType.QUESTION_PERIOD &&
+        !parent.isNullAware &&
         _nullType.lookUpGetter(parent.propertyName.name, _currentLibrary) ==
             null) {
       _errorReporter.reportErrorForNode(
@@ -1056,7 +1082,7 @@
           Element classElement = methodElement?.enclosingElement;
           return methodElement is MethodElement &&
               classElement is ClassElement &&
-              !classElement.type.isObject;
+              !classElement.isDartCoreObject;
         }
       }
       return false;
@@ -1110,6 +1136,20 @@
     }
   }
 
+  /// In "strict-inference" mode, check that [returnNode]'s return type is specified.
+  void _checkStrictInferenceReturnType(
+      AstNode returnType, AstNode reportNode, String displayName) {
+    if (!_strictInference) {
+      return;
+    }
+    if (returnType == null) {
+      _errorReporter.reportErrorForNode(
+          HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE,
+          reportNode,
+          [displayName]);
+    }
+  }
+
   bool _isLibraryInWorkspacePackage(LibraryElement library) {
     if (_workspacePackage == null || library == null) {
       // Better to not make a big claim that they _are_ in the same package,
@@ -2246,95 +2286,6 @@
   }
 }
 
-/// Instances of the class `EnumMemberBuilder` build the members in enum
-/// declarations.
-class EnumMemberBuilder extends RecursiveAstVisitor<void> {
-  /// The type provider used to access the types needed to build an element
-  /// model for enum declarations.
-  final TypeProvider _typeProvider;
-
-  /// Initialize a newly created enum member builder.
-  ///
-  /// @param typeProvider the type provider used to access the types needed to
-  ///        build an element model for enum declarations
-  EnumMemberBuilder(this._typeProvider);
-
-  @override
-  void visitEnumDeclaration(EnumDeclaration node) {
-    //
-    // Finish building the enum.
-    //
-    EnumElementImpl enumElement = node.name.staticElement as EnumElementImpl;
-    InterfaceType enumType = enumElement.type;
-    //
-    // Populate the fields.
-    //
-    List<FieldElement> fields = new List<FieldElement>();
-    List<PropertyAccessorElement> getters = new List<PropertyAccessorElement>();
-    InterfaceType intType = _typeProvider.intType;
-    String indexFieldName = "index";
-    FieldElementImpl indexField = new FieldElementImpl(indexFieldName, -1);
-    indexField.isFinal = true;
-    indexField.isSynthetic = true;
-    indexField.type = intType;
-    fields.add(indexField);
-    getters.add(_createGetter(indexField));
-    ConstFieldElementImpl valuesField = new ConstFieldElementImpl("values", -1);
-    valuesField.isStatic = true;
-    valuesField.isConst = true;
-    valuesField.isSynthetic = true;
-    valuesField.type = _typeProvider.listType.instantiate(<DartType>[enumType]);
-    fields.add(valuesField);
-    getters.add(_createGetter(valuesField));
-    //
-    // Build the enum constants.
-    //
-    NodeList<EnumConstantDeclaration> constants = node.constants;
-    List<DartObjectImpl> constantValues = new List<DartObjectImpl>();
-    int constantCount = constants.length;
-    for (int i = 0; i < constantCount; i++) {
-      EnumConstantDeclaration constant = constants[i];
-      FieldElementImpl constantField = constant.name.staticElement;
-      //
-      // Create a value for the constant.
-      //
-      Map<String, DartObjectImpl> fieldMap =
-          new HashMap<String, DartObjectImpl>();
-      fieldMap[indexFieldName] = new DartObjectImpl(intType, new IntState(i));
-      DartObjectImpl value =
-          new DartObjectImpl(enumType, new GenericState(fieldMap));
-      constantValues.add(value);
-      constantField.evaluationResult = new EvaluationResultImpl(value);
-      fields.add(constantField);
-      getters.add(constantField.getter);
-    }
-    //
-    // Build the value of the 'values' field.
-    //
-    valuesField.evaluationResult = new EvaluationResultImpl(
-        new DartObjectImpl(valuesField.type, new ListState(constantValues)));
-    // Update toString() return type.
-    {
-      MethodElementImpl toStringMethod = enumElement.methods[0];
-      toStringMethod.returnType = _typeProvider.stringType;
-      toStringMethod.type = new FunctionTypeImpl(toStringMethod);
-    }
-    //
-    // Finish building the enum.
-    //
-    enumElement.fields = fields;
-    enumElement.accessors = getters;
-    // Client code isn't allowed to invoke the constructor, so we do not model
-    // it.
-    super.visitEnumDeclaration(node);
-  }
-
-  /// Create a getter that corresponds to the given [field].
-  PropertyAccessorElement _createGetter(FieldElementImpl field) {
-    return new PropertyAccessorElementImpl_ImplicitGetter(field);
-  }
-}
-
 /// An [AstVisitor] that fills [UsedLocalElements].
 class GatherUsedLocalElementsVisitor extends RecursiveAstVisitor {
   final UsedLocalElements usedElements = new UsedLocalElements();
@@ -2715,7 +2666,7 @@
     Scope outerScope = nameScope;
     try {
       enclosingClass = node.declaredElement;
-      typeAnalyzer.thisType = enclosingClass?.type;
+      typeAnalyzer.thisType = enclosingClass?.thisType;
       if (enclosingClass == null) {
         AnalysisEngine.instance.logger.logInformation(
             "Missing element for class declaration ${node.name.name} in ${definingLibrary.source.fullName}",
@@ -2735,7 +2686,7 @@
       }
     } finally {
       nameScope = outerScope;
-      typeAnalyzer.thisType = outerType?.type;
+      typeAnalyzer.thisType = outerType?.thisType;
       enclosingClass = outerType;
       _enclosingClassDeclaration = null;
     }
@@ -2780,7 +2731,7 @@
 
   @override
   visitClassDeclaration(ClassDeclaration node) {
-    _currentType = node.declaredElement.type;
+    _currentType = node.declaredElement.thisType;
     super.visitClassDeclaration(node);
     _currentType = null;
   }
@@ -2831,7 +2782,7 @@
 
   @override
   visitMixinDeclaration(MixinDeclaration node) {
-    _currentType = node.declaredElement.type;
+    _currentType = node.declaredElement.thisType;
     super.visitMixinDeclaration(node);
     _currentType = null;
   }
@@ -2843,7 +2794,7 @@
   }
 }
 
-/// An AST visitor that is used to resolve the some of the nodes within a single
+/// An AST visitor that is used to resolve some of the nodes within a single
 /// compilation unit. The nodes that are skipped are those that are within
 /// function bodies.
 class PartialResolverVisitor extends ResolverVisitor {
@@ -3008,7 +2959,7 @@
   StaticTypeAnalyzer typeAnalyzer;
 
   /// The type system in use during resolution.
-  TypeSystem typeSystem;
+  Dart2TypeSystem typeSystem;
 
   /// The class declaration representing the class containing the current node,
   /// or `null` if the current node is not contained in a class.
@@ -3227,7 +3178,7 @@
   }) {
     _enclosingClassDeclaration = null;
     enclosingClass = enclosingClassElement;
-    typeAnalyzer.thisType = enclosingClass?.type;
+    typeAnalyzer.thisType = enclosingClass?.thisType;
     _enclosingFunction = enclosingExecutableElement;
   }
 
@@ -3235,7 +3186,7 @@
   void prepareToResolveMembersInClass(ClassDeclaration node) {
     _enclosingClassDeclaration = node;
     enclosingClass = node.declaredElement;
-    typeAnalyzer.thisType = enclosingClass?.type;
+    typeAnalyzer.thisType = enclosingClass?.thisType;
   }
 
   /// Visit the given [comment] if it is not `null`.
@@ -3495,12 +3446,12 @@
     ClassElement outerType = enclosingClass;
     try {
       enclosingClass = node.declaredElement;
-      typeAnalyzer.thisType = enclosingClass?.type;
+      typeAnalyzer.thisType = enclosingClass?.thisType;
       super.visitClassDeclaration(node);
       node.accept(elementResolver);
       node.accept(typeAnalyzer);
     } finally {
-      typeAnalyzer.thisType = outerType?.type;
+      typeAnalyzer.thisType = outerType?.thisType;
       enclosingClass = outerType;
       _enclosingClassDeclaration = null;
     }
@@ -3717,12 +3668,12 @@
     ClassElement outerType = enclosingClass;
     try {
       enclosingClass = node.declaredElement;
-      typeAnalyzer.thisType = enclosingClass?.type;
+      typeAnalyzer.thisType = enclosingClass?.thisType;
       super.visitEnumDeclaration(node);
       node.accept(elementResolver);
       node.accept(typeAnalyzer);
     } finally {
-      typeAnalyzer.thisType = outerType?.type;
+      typeAnalyzer.thisType = outerType?.thisType;
       enclosingClass = outerType;
       _enclosingClassDeclaration = null;
     }
@@ -3810,27 +3761,28 @@
       Expression iterable = forLoopParts.iterable;
       DeclaredIdentifier loopVariable;
       DartType valueType;
+      Element identifierElement;
       if (forLoopParts is ForEachPartsWithDeclaration) {
         loopVariable = forLoopParts.loopVariable;
         valueType = loopVariable?.type?.type ?? UnknownInferredType.instance;
       } else if (forLoopParts is ForEachPartsWithIdentifier) {
         SimpleIdentifier identifier = forLoopParts.identifier;
         identifier?.accept(this);
-        Element element = identifier?.staticElement;
-        if (element is VariableElement) {
-          valueType = element.type;
-        } else if (element is PropertyAccessorElement) {
-          if (element.parameters.isNotEmpty) {
-            valueType = element.parameters[0].type;
+        identifierElement = identifier?.staticElement;
+        if (identifierElement is VariableElement) {
+          valueType = identifierElement.type;
+        } else if (identifierElement is PropertyAccessorElement) {
+          if (identifierElement.parameters.isNotEmpty) {
+            valueType = identifierElement.parameters[0].type;
           }
         }
       }
 
       if (valueType != null) {
         InterfaceType targetType = (node.awaitKeyword == null)
-            ? typeProvider.iterableType
-            : typeProvider.streamType;
-        InferenceContext.setType(iterable, targetType.instantiate([valueType]));
+            ? typeProvider.iterableType2(valueType)
+            : typeProvider.streamType2(valueType);
+        InferenceContext.setType(iterable, targetType);
       }
       //
       // We visit the iterator before the loop variable because the loop
@@ -3840,7 +3792,10 @@
       _flowAnalysis?.loopVariable(loopVariable);
       loopVariable?.accept(this);
       _flowAnalysis?.flow?.forEach_bodyBegin(
-          _flowAnalysis.assignedVariables.writtenInNode(node));
+          _flowAnalysis.assignedVariables.writtenInNode(node),
+          identifierElement is VariableElement
+              ? identifierElement
+              : loopVariable.declaredElement);
       node.body?.accept(this);
       _flowAnalysis?.flow?.forEach_end();
 
@@ -3880,6 +3835,7 @@
       Expression iterable = forLoopParts.iterable;
       DeclaredIdentifier loopVariable;
       SimpleIdentifier identifier;
+      Element identifierElement;
       if (forLoopParts is ForEachPartsWithDeclaration) {
         loopVariable = forLoopParts.loopVariable;
       } else if (forLoopParts is ForEachPartsWithIdentifier) {
@@ -3893,20 +3849,20 @@
         valueType = typeAnnotation?.type ?? UnknownInferredType.instance;
       }
       if (identifier != null) {
-        Element element = identifier.staticElement;
-        if (element is VariableElement) {
-          valueType = element.type;
-        } else if (element is PropertyAccessorElement) {
-          if (element.parameters.isNotEmpty) {
-            valueType = element.parameters[0].type;
+        identifierElement = identifier.staticElement;
+        if (identifierElement is VariableElement) {
+          valueType = identifierElement.type;
+        } else if (identifierElement is PropertyAccessorElement) {
+          if (identifierElement.parameters.isNotEmpty) {
+            valueType = identifierElement.parameters[0].type;
           }
         }
       }
       if (valueType != null) {
         InterfaceType targetType = (node.awaitKeyword == null)
-            ? typeProvider.iterableType
-            : typeProvider.streamType;
-        InferenceContext.setType(iterable, targetType.instantiate([valueType]));
+            ? typeProvider.iterableType2(valueType)
+            : typeProvider.streamType2(valueType);
+        InferenceContext.setType(iterable, targetType);
       }
       //
       // We visit the iterator before the loop variable because the loop variable
@@ -3917,8 +3873,10 @@
       loopVariable?.accept(this);
 
       _flowAnalysis?.flow?.forEach_bodyBegin(
-        _flowAnalysis.assignedVariables.writtenInNode(node),
-      );
+          _flowAnalysis.assignedVariables.writtenInNode(node),
+          identifierElement is VariableElement
+              ? identifierElement
+              : loopVariable.declaredElement);
 
       Statement body = node.body;
       if (body != null) {
@@ -4124,7 +4082,7 @@
       if (typeArguments.arguments.length == 1) {
         DartType elementType = typeArguments.arguments[0].type;
         if (!elementType.isDynamic) {
-          listType = typeProvider.listType.instantiate([elementType]);
+          listType = typeProvider.listType2(elementType);
         }
       }
     } else {
@@ -4132,8 +4090,7 @@
     }
     if (listType != null) {
       DartType elementType = listType.typeArguments[0];
-      DartType iterableType =
-          typeProvider.iterableType.instantiate([elementType]);
+      DartType iterableType = typeProvider.iterableType2(elementType);
       _pushCollectionTypesDownToAll(node.elements,
           elementType: elementType, iterableType: iterableType);
       InferenceContext.setType(node, listType);
@@ -4192,12 +4149,12 @@
     ClassElement outerType = enclosingClass;
     try {
       enclosingClass = node.declaredElement;
-      typeAnalyzer.thisType = enclosingClass?.type;
+      typeAnalyzer.thisType = enclosingClass?.thisType;
       super.visitMixinDeclaration(node);
       node.accept(elementResolver);
       node.accept(typeAnalyzer);
     } finally {
-      typeAnalyzer.thisType = outerType?.type;
+      typeAnalyzer.thisType = outerType?.thisType;
       enclosingClass = outerType;
       _enclosingMixinDeclaration = null;
     }
@@ -4300,7 +4257,7 @@
     if (literalResolution.kind == _LiteralResolutionKind.set) {
       if (typeArguments != null && typeArguments.length == 1) {
         var elementType = typeArguments[0].type;
-        literalType = typeProvider.setType.instantiate([elementType]);
+        literalType = typeProvider.setType2(elementType);
       } else {
         literalType = typeAnalyzer.inferSetTypeDownwards(
             node, literalResolution.contextType);
@@ -4309,7 +4266,7 @@
       if (typeArguments != null && typeArguments.length == 2) {
         var keyType = typeArguments[0].type;
         var valueType = typeArguments[1].type;
-        literalType = typeProvider.mapType.instantiate([keyType, valueType]);
+        literalType = typeProvider.mapType2(keyType, valueType);
       } else {
         literalType = typeAnalyzer.inferMapTypeDownwards(
             node, literalResolution.contextType);
@@ -4322,8 +4279,7 @@
       List<DartType> typeArguments = literalType.typeArguments;
       if (typeArguments.length == 1) {
         DartType elementType = literalType.typeArguments[0];
-        DartType iterableType =
-            typeProvider.iterableType.instantiate([elementType]);
+        DartType iterableType = typeProvider.iterableType2(elementType);
         _pushCollectionTypesDownToAll(node.elements,
             elementType: elementType, iterableType: iterableType);
         if (!_uiAsCodeEnabled &&
@@ -4561,10 +4517,9 @@
       if (node.star != null) {
         // If this is a yield*, then we wrap the element return type
         // If it's synchronous, we expect Iterable<T>, otherwise Stream<T>
-        InterfaceType wrapperType = _enclosingFunction.isSynchronous
-            ? typeProvider.iterableType
-            : typeProvider.streamType;
-        type = wrapperType.instantiate(<DartType>[type]);
+        type = _enclosingFunction.isSynchronous
+            ? typeProvider.iterableType2(type)
+            : typeProvider.streamType2(type);
       }
       InferenceContext.setType(e, type);
     }
@@ -4575,12 +4530,12 @@
       if (node.star != null) {
         // If this is a yield*, then we unwrap the element return type
         // If it's synchronous, we expect Iterable<T>, otherwise Stream<T>
-        InterfaceType wrapperType = _enclosingFunction.isSynchronous
-            ? typeProvider.iterableType
-            : typeProvider.streamType;
         if (type is InterfaceType) {
+          ClassElement wrapperElement = _enclosingFunction.isSynchronous
+              ? typeProvider.iterableElement
+              : typeProvider.streamElement;
           var asInstanceType =
-              (type as InterfaceTypeImpl).asInstanceOf(wrapperType.element);
+              (type as InterfaceTypeImpl).asInstanceOf(wrapperElement);
           if (asInstanceType != null) {
             type = asInstanceType.typeArguments[0];
           }
@@ -4607,13 +4562,19 @@
       if (isGenerator) {
         // If it's sync* we expect Iterable<T>
         // If it's async* we expect Stream<T>
-        InterfaceType rawType = isAsynchronous
-            ? typeProvider.streamType
-            : typeProvider.iterableType;
         // Match the types to instantiate the type arguments if possible
         List<DartType> targs = declaredType.typeArguments;
-        if (targs.length == 1 && rawType.instantiate(targs) == declaredType) {
-          return targs[0];
+        if (targs.length == 1) {
+          var arg = targs[0];
+          if (isAsynchronous) {
+            if (typeProvider.streamType2(arg) == declaredType) {
+              return arg;
+            }
+          } else {
+            if (typeProvider.iterableType2(arg) == declaredType) {
+              return arg;
+            }
+          }
         }
       }
       // async functions expect `Future<T> | T`
@@ -4673,8 +4634,8 @@
     } else if (literal.elements.isEmpty) {
       return _LiteralResolution(
           _LiteralResolutionKind.map,
-          typeProvider.mapType.instantiate(
-              [typeProvider.dynamicType, typeProvider.dynamicType]));
+          typeProvider.mapType2(
+              typeProvider.dynamicType, typeProvider.dynamicType));
     }
     return _LiteralResolution(_LiteralResolutionKind.ambiguous, null);
   }
@@ -4691,7 +4652,7 @@
     if (type.isDartAsyncFutureOr) {
       return type;
     }
-    return typeProvider.futureOrType.instantiate([type]);
+    return typeProvider.futureOrType2(type);
   }
 
   /// If [contextType] is defined and is a subtype of `Iterable<Object>` and
@@ -4736,12 +4697,10 @@
       NodeList<TypeAnnotation> arguments = typeArgumentList.arguments;
       if (arguments.length == 1) {
         return _LiteralResolution(_LiteralResolutionKind.set,
-            typeProvider.setType.instantiate([arguments[0].type]));
+            typeProvider.setType2(arguments[0].type));
       } else if (arguments.length == 2) {
-        return _LiteralResolution(
-            _LiteralResolutionKind.map,
-            typeProvider.mapType
-                .instantiate([arguments[0].type, arguments[1].type]));
+        return _LiteralResolution(_LiteralResolutionKind.map,
+            typeProvider.mapType2(arguments[0].type, arguments[1].type));
       }
     }
     return _LiteralResolution(_LiteralResolutionKind.ambiguous, null);
@@ -4765,20 +4724,23 @@
       DartType uninstantiatedType, TypeArgumentList typeArguments,
       {AstNode errorNode, bool isConst: false}) {
     errorNode ??= inferenceNode;
-    TypeSystem ts = typeSystem;
     if (typeArguments == null &&
         uninstantiatedType is FunctionType &&
-        uninstantiatedType.typeFormals.isNotEmpty &&
-        ts is Dart2TypeSystem) {
-      return ts.inferGenericFunctionOrType<FunctionType>(
-          uninstantiatedType,
-          const <ParameterElement>[],
-          const <DartType>[],
-          InferenceContext.getContext(inferenceNode),
-          downwards: true,
-          isConst: isConst,
-          errorReporter: errorReporter,
-          errorNode: errorNode);
+        uninstantiatedType.typeFormals.isNotEmpty) {
+      var typeArguments = typeSystem.inferGenericFunctionOrType(
+        typeParameters: uninstantiatedType.typeFormals,
+        parameters: const <ParameterElement>[],
+        declaredReturnType: uninstantiatedType.returnType,
+        argumentTypes: const <DartType>[],
+        contextReturnType: InferenceContext.getContext(inferenceNode),
+        downwards: true,
+        isConst: isConst,
+        errorReporter: errorReporter,
+        errorNode: errorNode,
+      );
+      if (typeArguments != null) {
+        return uninstantiatedType.instantiate(typeArguments);
+      }
     }
     return null;
   }
@@ -5809,7 +5771,7 @@
 ///
 /// The client must set [nameScope] before calling [resolveTypeName].
 class TypeNameResolver {
-  final TypeSystem typeSystem;
+  final Dart2TypeSystem typeSystem;
   final DartType dynamicType;
   final bool isNonNullableUnit;
   final AnalysisOptionsImpl analysisOptions;
@@ -6064,7 +6026,9 @@
       type = DynamicTypeImpl.instance;
     } else if (element is NeverElementImpl) {
       _setElement(typeName, element);
-      type = element.type;
+      type = element.instantiate(
+        nullabilitySuffix: _getNullability(node.question != null),
+      );
     } else if (element is FunctionTypeAliasElement) {
       _setElement(typeName, element);
       type = element.type as TypeImpl;
@@ -6141,9 +6105,8 @@
       }
     } else {
       if (element is GenericTypeAliasElementImpl) {
-        var ts = typeSystem as Dart2TypeSystem;
         List<DartType> typeArguments =
-            ts.instantiateTypeFormalsToBounds2(element);
+            typeSystem.instantiateTypeFormalsToBounds2(element);
         type = GenericTypeAliasElementImpl.typeAfterSubstitution(
                 element, typeArguments) ??
             dynamicType;
@@ -6255,24 +6218,25 @@
   /// If the [node] is the type name in a redirected factory constructor,
   /// infer type arguments using the enclosing class declaration. Return `null`
   /// otherwise.
-  InterfaceTypeImpl _inferTypeArgumentsForRedirectedConstructor(
-      TypeName node, DartType type) {
+  List<DartType> _inferTypeArgumentsForRedirectedConstructor(
+      TypeName node, ClassElement typeElement) {
     AstNode constructorName = node.parent;
     AstNode enclosingConstructor = constructorName?.parent;
-    TypeSystem ts = typeSystem;
     if (constructorName is ConstructorName &&
         enclosingConstructor is ConstructorDeclaration &&
-        enclosingConstructor.redirectedConstructor == constructorName &&
-        type is InterfaceType &&
-        ts is Dart2TypeSystem) {
+        enclosingConstructor.redirectedConstructor == constructorName) {
       ClassOrMixinDeclaration enclosingClassNode = enclosingConstructor.parent;
-      ClassElement enclosingClassElement = enclosingClassNode.declaredElement;
-      if (enclosingClassElement == type.element) {
-        return type;
+      var enclosingClassElement = enclosingClassNode.declaredElement;
+      if (enclosingClassElement == typeElement) {
+        return typeElement.thisType.typeArguments;
       } else {
-        InterfaceType contextType = enclosingClassElement.type;
-        return ts.inferGenericFunctionOrType(
-            type, const <ParameterElement>[], const <DartType>[], contextType);
+        return typeSystem.inferGenericFunctionOrType(
+          typeParameters: typeElement.typeParameters,
+          parameters: const [],
+          declaredReturnType: typeElement.thisType,
+          argumentTypes: const [],
+          contextReturnType: enclosingClassElement.thisType,
+        );
       }
     }
     return null;
@@ -6382,13 +6346,10 @@
     } else if (parameterCount == 0) {
       typeArguments = const <DartType>[];
     } else {
-      var redirectedType =
-          _inferTypeArgumentsForRedirectedConstructor(node, element.type);
-      if (redirectedType != null) {
-        typeArguments = redirectedType.typeArguments;
-      } else {
-        var ts = typeSystem as Dart2TypeSystem;
-        typeArguments = ts.instantiateTypeFormalsToBounds2(element);
+      typeArguments =
+          _inferTypeArgumentsForRedirectedConstructor(node, element);
+      if (typeArguments == null) {
+        typeArguments = typeSystem.instantiateTypeFormalsToBounds2(element);
       }
     }
 
@@ -6618,16 +6579,24 @@
   /// Return the type representing 'Future<dynamic>'.
   InterfaceType get futureDynamicType;
 
+  /// Return the element representing the built-in class 'Future'.
+  ClassElement get futureElement;
+
   /// Return the type representing 'Future<Null>'.
   InterfaceType get futureNullType;
 
+  /// Return the element representing the built-in class 'FutureOr'.
+  ClassElement get futureOrElement;
+
   /// Return the type representing 'FutureOr<Null>'.
   InterfaceType get futureOrNullType;
 
   /// Return the type representing the built-in type 'FutureOr'.
+  @Deprecated('Use futureOrType2() instead.')
   InterfaceType get futureOrType;
 
   /// Return the type representing the built-in type 'Future'.
+  @Deprecated('Use futureType2() instead.')
   InterfaceType get futureType;
 
   /// Return the type representing the built-in type 'int'.
@@ -6636,19 +6605,31 @@
   /// Return the type representing the type 'Iterable<dynamic>'.
   InterfaceType get iterableDynamicType;
 
+  /// Return the element representing the built-in class 'Iterable'.
+  ClassElement get iterableElement;
+
   /// Return the type representing the type 'Iterable<Object>'.
   InterfaceType get iterableObjectType;
 
   /// Return the type representing the built-in type 'Iterable'.
+  @Deprecated('Use iterableType2() instead.')
   InterfaceType get iterableType;
 
+  /// Return the element representing the built-in class 'List'.
+  ClassElement get listElement;
+
   /// Return the type representing the built-in type 'List'.
+  @Deprecated('Use listType2() instead.')
   InterfaceType get listType;
 
+  /// Return the element representing the built-in class 'Map'.
+  ClassElement get mapElement;
+
   /// Return the type representing 'Map<Object, Object>'.
   InterfaceType get mapObjectObjectType;
 
   /// Return the type representing the built-in type 'Map'.
+  @Deprecated('Use mapType2() instead.')
   InterfaceType get mapType;
 
   /// Return the type representing the built-in type 'Never'.
@@ -6670,7 +6651,11 @@
   /// Return the type representing the built-in type 'Object'.
   InterfaceType get objectType;
 
+  /// Return the element representing the built-in class 'Set'.
+  ClassElement get setElement;
+
   /// Return the type representing the built-in type 'Set'.
+  @Deprecated('Use setType2() instead.')
   InterfaceType get setType;
 
   /// Return the type representing the built-in type 'StackTrace'.
@@ -6679,12 +6664,19 @@
   /// Return the type representing 'Stream<dynamic>'.
   InterfaceType get streamDynamicType;
 
+  /// Return the element representing the built-in class 'Stream'.
+  ClassElement get streamElement;
+
   /// Return the type representing the built-in type 'Stream'.
+  @Deprecated('Use streamType2() instead.')
   InterfaceType get streamType;
 
   /// Return the type representing the built-in type 'String'.
   InterfaceType get stringType;
 
+  /// Return the element representing the built-in class 'Symbol'.
+  ClassElement get symbolElement;
+
   /// Return the type representing the built-in type 'Symbol'.
   InterfaceType get symbolType;
 
@@ -6694,6 +6686,14 @@
   /// Return the type representing the built-in type `void`.
   VoidType get voidType;
 
+  /// Return the instantiation of the built-in class 'FutureOr' with the
+  /// given [valueType]. The type has the nullability suffix of this provider.
+  InterfaceType futureOrType2(DartType valueType);
+
+  /// Return the instantiation of the built-in class 'Future' with the
+  /// given [valueType]. The type has the nullability suffix of this provider.
+  InterfaceType futureType2(DartType valueType);
+
   /// Return 'true' if [id] is the name of a getter on
   /// the Object type.
   bool isObjectGetter(String id);
@@ -6705,6 +6705,27 @@
   /// Return 'true' if [id] is the name of a method on
   /// the Object type.
   bool isObjectMethod(String id);
+
+  /// Return the instantiation of the built-in class 'Iterable' with the
+  /// given [elementType]. The type has the nullability suffix of this provider.
+  InterfaceType iterableType2(DartType elementType);
+
+  /// Return the instantiation of the built-in class 'List' with the
+  /// given [elementType]. The type has the nullability suffix of this provider.
+  InterfaceType listType2(DartType elementType);
+
+  /// Return the instantiation of the built-in class 'List' with the
+  /// given [keyType] and [valueType]. The type has the nullability suffix of
+  /// this provider.
+  InterfaceType mapType2(DartType keyType, DartType valueType);
+
+  /// Return the instantiation of the built-in class 'Set' with the
+  /// given [elementType]. The type has the nullability suffix of this provider.
+  InterfaceType setType2(DartType elementType);
+
+  /// Return the instantiation of the built-in class 'Stream' with the
+  /// given [elementType]. The type has the nullability suffix of this provider.
+  InterfaceType streamType2(DartType elementType);
 }
 
 /// Modes in which [TypeResolverVisitor] works.
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index 1152e24..dd872c2 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -33,7 +33,7 @@
   String get encoding => uri.toString();
 
   @override
-  String get fullName => encoding;
+  String get fullName => '$uri';
 
   @override
   int get hashCode => uri.hashCode;
@@ -50,6 +50,8 @@
 
 /**
  * A cache used to override the default content of a [Source].
+ *
+ * TODO(scheglov) Remove it.
  */
 class ContentCache {
   /**
@@ -388,6 +390,7 @@
    * @return an encoded representation of this source
    * See [SourceFactory.fromEncoding].
    */
+  @deprecated
   String get encoding;
 
   /**
@@ -595,7 +598,6 @@
    * @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
-   * See [Source.encoding].
    */
   Source fromEncoding(String encoding);
 
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 3a98084..91b6336 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -7,6 +7,7 @@
 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/analysis/driver.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
@@ -51,7 +52,7 @@
   /**
    * The type system in use for static type analysis.
    */
-  TypeSystem _typeSystem;
+  Dart2TypeSystem _typeSystem;
 
   /**
    * The type representing the type 'dynamic'.
@@ -90,6 +91,12 @@
     _strictInference = analysisOptions.strictInference;
   }
 
+  NullabilitySuffix get _noneOrStarSuffix {
+    return _nonNullableEnabled
+        ? NullabilitySuffix.none
+        : NullabilitySuffix.star;
+  }
+
   /**
    * Return `true` if NNBD is enabled for this compilation unit.
    */
@@ -117,12 +124,11 @@
       FormalParameterList node, DartType functionType) {
     bool inferred = false;
     if (node != null && functionType is FunctionType) {
-      var ts = _typeSystem as Dart2TypeSystem;
       void inferType(ParameterElementImpl p, DartType inferredType) {
         // Check that there is no declared type, and that we have not already
         // inferred a type in some fashion.
         if (p.hasImplicitType && (p.type == null || p.type.isDynamic)) {
-          inferredType = ts.upperBoundForType(inferredType);
+          inferredType = _typeSystem.upperBoundForType(inferredType);
           if (inferredType.isDartCoreNull) {
             inferredType = _typeProvider.objectType;
           }
@@ -162,7 +168,12 @@
   DartType inferListType(ListLiteral node, {bool downwards: false}) {
     DartType contextType = InferenceContext.getContext(node);
 
-    var ts = _typeSystem as Dart2TypeSystem;
+    var element = _typeProvider.listElement;
+    var typeParameters = element.typeParameters;
+    var genericElementType = typeParameters[0].instantiate(
+      nullabilitySuffix: _noneOrStarSuffix,
+    );
+
     List<DartType> elementTypes;
     List<ParameterElement> parameters;
 
@@ -178,12 +189,9 @@
           .map((element) => _computeElementType(element))
           .where((t) => t != null)
           .toList();
-      TypeParameterType listTypeParam =
-          _typeProvider.listType.typeParameters[0].type;
-      ParameterElementImpl syntheticParamElement =
-          new ParameterElementImpl.synthetic(
-              'element', listTypeParam, ParameterKind.POSITIONAL);
-      parameters = new List.filled(elementTypes.length, syntheticParamElement);
+      var syntheticParameter = ParameterElementImpl.synthetic(
+          'element', genericElementType, ParameterKind.POSITIONAL);
+      parameters = List.filled(elementTypes.length, syntheticParameter);
     }
     if (_strictInference && parameters.isEmpty && contextType == null) {
       // We cannot infer the type of a collection literal with no elements, and
@@ -192,13 +200,22 @@
       _resolver.errorReporter.reportErrorForNode(
           HintCode.INFERENCE_FAILURE_ON_COLLECTION_LITERAL, node, ['List']);
     }
-    InterfaceType inferred = ts.inferGenericFunctionOrType<InterfaceType>(
-        _typeProvider.listType, parameters, elementTypes, contextType,
-        downwards: downwards,
-        isConst: node.isConst,
-        errorReporter: _resolver.errorReporter,
-        errorNode: node);
-    return inferred;
+
+    var typeArguments = _typeSystem.inferGenericFunctionOrType(
+      typeParameters: typeParameters,
+      parameters: parameters,
+      declaredReturnType: element.thisType,
+      argumentTypes: elementTypes,
+      contextReturnType: contextType,
+      downwards: downwards,
+      isConst: node.isConst,
+      errorReporter: _resolver.errorReporter,
+      errorNode: node,
+    );
+    return element.instantiate(
+      typeArguments: typeArguments,
+      nullabilitySuffix: _noneOrStarSuffix,
+    );
   }
 
   ParameterizedType inferMapTypeDownwards(
@@ -207,14 +224,22 @@
       return null;
     }
 
-    var ts = _typeSystem as Dart2TypeSystem;
-    ParameterizedType inferred = ts.inferGenericFunctionOrType(
-        _typeProvider.mapType, [], [], contextType,
-        downwards: true,
-        isConst: node.isConst,
-        errorReporter: _resolver.errorReporter,
-        errorNode: node);
-    return inferred;
+    var element = _typeProvider.mapElement;
+    var typeArguments = _typeSystem.inferGenericFunctionOrType(
+      typeParameters: element.typeParameters,
+      parameters: const [],
+      declaredReturnType: element.thisType,
+      argumentTypes: const [],
+      contextReturnType: contextType,
+      downwards: true,
+      isConst: node.isConst,
+      errorReporter: _resolver.errorReporter,
+      errorNode: node,
+    );
+    return element.instantiate(
+      typeArguments: typeArguments,
+      nullabilitySuffix: _noneOrStarSuffix,
+    );
   }
 
   DartType inferSetTypeDownwards(SetOrMapLiteral node, DartType contextType) {
@@ -222,14 +247,22 @@
       return null;
     }
 
-    var ts = _typeSystem as Dart2TypeSystem;
-    DartType inferred = ts.inferGenericFunctionOrType<InterfaceType>(
-        _typeProvider.setType, [], [], contextType,
-        downwards: true,
-        isConst: node.isConst,
-        errorReporter: _resolver.errorReporter,
-        errorNode: node);
-    return inferred;
+    var element = _typeProvider.setElement;
+    var typeArguments = _typeSystem.inferGenericFunctionOrType(
+      typeParameters: element.typeParameters,
+      parameters: const [],
+      declaredReturnType: element.thisType,
+      argumentTypes: const [],
+      contextReturnType: contextType,
+      downwards: true,
+      isConst: node.isConst,
+      errorReporter: _resolver.errorReporter,
+      errorNode: node,
+    );
+    return element.instantiate(
+      typeArguments: typeArguments,
+      nullabilitySuffix: _noneOrStarSuffix,
+    );
   }
 
   /**
@@ -593,8 +626,8 @@
   @override
   void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
     _inferGenericInvocationExpression(node);
-    DartType staticType = _computeInvokeReturnType(node.staticInvokeType,
-        isNullableInvoke: false);
+    DartType staticType =
+        _computeInvokeReturnType(node.staticInvokeType, isNullAware: false);
     _recordStaticType(node, staticType);
   }
 
@@ -703,14 +736,11 @@
         }
       }
       _recordStaticType(
-          node,
-          _nonNullable(
-              _typeProvider.listType.instantiate(<DartType>[staticType])));
+          node, _nonNullable(_typeProvider.listType2(staticType)));
       return;
     }
 
-    DartType listDynamicType =
-        _typeProvider.listType.instantiate(<DartType>[_dynamicType]);
+    DartType listDynamicType = _typeProvider.listType2(_dynamicType);
 
     // If there are no type arguments, try to infer some arguments.
     DartType inferred = inferListType(node);
@@ -777,7 +807,7 @@
     if (!inferredStaticType) {
       DartType staticStaticType = _computeInvokeReturnType(
           node.staticInvokeType,
-          isNullableInvoke: node.operator?.type == TokenType.QUESTION_PERIOD);
+          isNullAware: node.isNullAware);
       _recordStaticType(node, staticStaticType);
     }
   }
@@ -1005,18 +1035,14 @@
         (node as SetOrMapLiteralImpl).becomeSet();
         var elementType = _getType(typeArguments[0]) ?? _dynamicType;
         _recordStaticType(
-            node,
-            _nonNullable(
-                _typeProvider.setType.instantiate(<DartType>[elementType])));
+            node, _nonNullable(_typeProvider.setType2(elementType)));
         return;
       } else if (typeArguments.length == 2) {
         (node as SetOrMapLiteralImpl).becomeMap();
         var keyType = _getType(typeArguments[0]) ?? _dynamicType;
         var valueType = _getType(typeArguments[1]) ?? _dynamicType;
         _recordStaticType(
-            node,
-            _nonNullable(_typeProvider.mapType
-                .instantiate(<DartType>[keyType, valueType])));
+            node, _nonNullable(_typeProvider.mapType2(keyType, valueType)));
         return;
       }
       // If we get here, then a nonsense number of type arguments were provided,
@@ -1026,10 +1052,10 @@
     if (literalType.isDynamic) {
       // The literal is ambiguous, and further analysis won't resolve the
       // ambiguity.  Leave it as neither a set nor a map.
-    } else if (literalType.element == _typeProvider.mapType.element) {
+    } else if (literalType.element == _typeProvider.mapElement) {
       (node as SetOrMapLiteralImpl).becomeMap();
     } else {
-      assert(literalType.element == _typeProvider.setType.element);
+      assert(literalType.element == _typeProvider.setElement);
       (node as SetOrMapLiteralImpl).becomeSet();
     }
     if (_strictInference &&
@@ -1273,7 +1299,7 @@
         if (_typeSystem.isSubtypeOf(
             expressionType, _typeProvider.iterableObjectType)) {
           InterfaceType iterableType = (expressionType as InterfaceTypeImpl)
-              .asInstanceOf(_typeProvider.iterableType.element);
+              .asInstanceOf(_typeProvider.iterableElement);
           return iterableType.typeArguments[0];
         }
       } else if (expressionType.isDynamic) {
@@ -1292,7 +1318,7 @@
    * type that is being invoked.
    */
   DartType /*!*/ _computeInvokeReturnType(DartType type,
-      {@required bool isNullableInvoke}) {
+      {@required bool isNullAware}) {
     TypeImpl /*!*/ returnType;
     if (type is InterfaceType) {
       MethodElement callMethod = type.lookUpMethod(
@@ -1304,7 +1330,7 @@
       returnType = _dynamicType;
     }
 
-    if (isNullableInvoke && _nonNullableEnabled) {
+    if (isNullAware && _nonNullableEnabled) {
       returnType = _typeSystem.makeNullable(returnType);
     }
 
@@ -1320,16 +1346,16 @@
    */
   DartType _computeReturnTypeOfFunction(FunctionBody body, DartType type) {
     if (body.isGenerator) {
-      InterfaceType genericType = body.isAsynchronous
-          ? _typeProvider.streamType
-          : _typeProvider.iterableType;
-      return _nonNullable(genericType.instantiate(<DartType>[type]));
+      InterfaceType generatedType = body.isAsynchronous
+          ? _typeProvider.streamType2(type)
+          : _typeProvider.iterableType2(type);
+      return _nonNullable(generatedType);
     } else if (body.isAsynchronous) {
       if (type.isDartAsyncFutureOr) {
         type = (type as InterfaceType).typeArguments[0];
       }
-      DartType futureType = _typeProvider.futureType
-          .instantiate(<DartType>[_typeSystem.flatten(type)]);
+      DartType futureType =
+          _typeProvider.futureType2(_typeSystem.flatten(type));
       return _nonNullable(futureType);
     } else {
       return type;
@@ -1351,10 +1377,10 @@
       FunctionType propertyType = element.type;
       if (propertyType != null) {
         return _computeInvokeReturnType(propertyType.returnType,
-            isNullableInvoke: false);
+            isNullAware: false);
       }
     } else if (element is ExecutableElement) {
-      return _computeInvokeReturnType(element.type, isNullableInvoke: false);
+      return _computeInvokeReturnType(element.type, isNullAware: false);
     }
     return _dynamicType;
   }
@@ -1526,7 +1552,7 @@
         if (_typeSystem.isSubtypeOf(
             expressionType, _typeProvider.iterableObjectType)) {
           InterfaceType iterableType = (expressionType as InterfaceTypeImpl)
-              .asInstanceOf(_typeProvider.iterableType.element);
+              .asInstanceOf(_typeProvider.iterableElement);
           return _InferredCollectionElementTypeInformation(
               elementType: iterableType.typeArguments[0],
               keyType: null,
@@ -1534,7 +1560,7 @@
         } else if (_typeSystem.isSubtypeOf(
             expressionType, _typeProvider.mapObjectObjectType)) {
           InterfaceType mapType = (expressionType as InterfaceTypeImpl)
-              .asInstanceOf(_typeProvider.mapType.element);
+              .asInstanceOf(_typeProvider.mapElement);
           List<DartType> typeArguments = mapType.typeArguments;
           return _InferredCollectionElementTypeInformation(
               elementType: null,
@@ -1590,8 +1616,8 @@
         iterableType = iterableType.resolveToBound(_typeProvider.objectType);
 
         ClassElement iteratedElement = (awaitKeyword == null)
-            ? _typeProvider.iterableType.element
-            : _typeProvider.streamType.element;
+            ? _typeProvider.iterableElement
+            : _typeProvider.streamElement;
 
         InterfaceType iteratedType = iterableType is InterfaceTypeImpl
             ? iterableType.asInstanceOf(iteratedElement)
@@ -1644,11 +1670,9 @@
       ArgumentList argumentList,
       AstNode errorNode,
       {bool isConst: false}) {
-    TypeSystem ts = _typeSystem;
     if (typeArguments == null &&
         fnType is FunctionType &&
-        fnType.typeFormals.isNotEmpty &&
-        ts is Dart2TypeSystem) {
+        fnType.typeFormals.isNotEmpty) {
       // Get the parameters that correspond to the uninstantiated generic.
       List<ParameterElement> rawParameters =
           ResolverVisitor.resolveArgumentsToParameters(
@@ -1663,11 +1687,16 @@
           argTypes.add(argumentList.arguments[i].staticType);
         }
       }
-      var typeArgs = ts.inferGenericFunctionOrType2<FunctionType>(
-          fnType, params, argTypes, InferenceContext.getContext(node),
-          isConst: isConst,
-          errorReporter: _resolver.errorReporter,
-          errorNode: errorNode);
+      var typeArgs = _typeSystem.inferGenericFunctionOrType(
+        typeParameters: fnType.typeFormals,
+        parameters: params,
+        declaredReturnType: fnType.returnType,
+        argumentTypes: argTypes,
+        contextReturnType: InferenceContext.getContext(node),
+        isConst: isConst,
+        errorReporter: _resolver.errorReporter,
+        errorNode: errorNode,
+      );
       if (node is InvocationExpressionImpl) {
         node.typeArgumentTypes = typeArgs;
       }
@@ -1961,12 +1990,9 @@
     SimpleIdentifier identifier,
     DartType tearOffType,
   ) {
-    TypeSystem ts = _typeSystem;
     var context = InferenceContext.getContext(expression);
-    if (context is FunctionType &&
-        tearOffType is FunctionType &&
-        ts is Dart2TypeSystem) {
-      var typeArguments = ts.inferFunctionTypeInstantiation(
+    if (context is FunctionType && tearOffType is FunctionType) {
+      var typeArguments = _typeSystem.inferFunctionTypeInstantiation(
         context,
         tearOffType,
         errorReporter: _resolver.errorReporter,
@@ -2078,54 +2104,69 @@
   DartType _toMapType(SetOrMapLiteral node, DartType contextType,
       List<_InferredCollectionElementTypeInformation> inferredTypes) {
     DartType dynamicType = _typeProvider.dynamicType;
-    List<DartType> keyTypes = [];
-    List<DartType> valueTypes = [];
-    for (int i = 0; i < inferredTypes.length; i++) {
-      keyTypes.add(inferredTypes[i].keyType ?? dynamicType);
-      valueTypes.add(inferredTypes[i].valueType ?? dynamicType);
+
+    var element = _typeProvider.mapElement;
+    var typeParameters = element.typeParameters;
+    var genericKeyType = typeParameters[0].instantiate(
+      nullabilitySuffix: _noneOrStarSuffix,
+    );
+    var genericValueType = typeParameters[1].instantiate(
+      nullabilitySuffix: _noneOrStarSuffix,
+    );
+
+    var parameters = List<ParameterElement>(2 * inferredTypes.length);
+    var argumentTypes = List<DartType>(2 * inferredTypes.length);
+    for (var i = 0; i < inferredTypes.length; i++) {
+      parameters[2 * i + 0] = ParameterElementImpl.synthetic(
+          'key', genericKeyType, ParameterKind.POSITIONAL);
+      parameters[2 * i + 1] = ParameterElementImpl.synthetic(
+          'value', genericValueType, ParameterKind.POSITIONAL);
+      argumentTypes[2 * i + 0] = inferredTypes[i].keyType ?? dynamicType;
+      argumentTypes[2 * i + 1] = inferredTypes[i].valueType ?? dynamicType;
     }
-    TypeParameterType keyTypeParam =
-        _typeProvider.mapType.typeParameters[0].type;
-    TypeParameterType valueTypeParam =
-        _typeProvider.mapType.typeParameters[1].type;
-    ParameterElementImpl syntheticKeyParameter =
-        new ParameterElementImpl.synthetic(
-            'key', keyTypeParam, ParameterKind.POSITIONAL);
-    ParameterElementImpl syntheticValueParameter =
-        new ParameterElementImpl.synthetic(
-            'value', valueTypeParam, ParameterKind.POSITIONAL);
-    List<ParameterElement> typeParameters =
-        new List.filled(keyTypes.length, syntheticKeyParameter, growable: true)
-          ..addAll(new List.filled(valueTypes.length, syntheticValueParameter));
-    List<DartType> elementTypes = new List<DartType>.from(keyTypes)
-      ..addAll(valueTypes);
-    return (_typeSystem as Dart2TypeSystem).inferGenericFunctionOrType(
-        _typeProvider.mapType, typeParameters, elementTypes, contextType,
-        isConst: node.isConst,
-        errorReporter: _resolver.errorReporter,
-        errorNode: node);
+
+    var typeArguments = _typeSystem.inferGenericFunctionOrType(
+      typeParameters: typeParameters,
+      parameters: parameters,
+      declaredReturnType: element.thisType,
+      argumentTypes: argumentTypes,
+      contextReturnType: contextType,
+    );
+    return element.instantiate(
+      typeArguments: typeArguments,
+      nullabilitySuffix: _noneOrStarSuffix,
+    );
   }
 
   DartType _toSetType(SetOrMapLiteral node, DartType contextType,
       List<_InferredCollectionElementTypeInformation> inferredTypes) {
     DartType dynamicType = _typeProvider.dynamicType;
-    List<DartType> elementTypes = [];
-    for (int i = 0; i < inferredTypes.length; i++) {
-      elementTypes.add(inferredTypes[i].elementType ?? dynamicType);
+
+    var element = _typeProvider.setElement;
+    var typeParameters = element.typeParameters;
+    var genericElementType = typeParameters[0].instantiate(
+      nullabilitySuffix: _noneOrStarSuffix,
+    );
+
+    var parameters = List<ParameterElement>(inferredTypes.length);
+    var argumentTypes = List<DartType>(inferredTypes.length);
+    for (var i = 0; i < inferredTypes.length; i++) {
+      parameters[i] = ParameterElementImpl.synthetic(
+          'element', genericElementType, ParameterKind.POSITIONAL);
+      argumentTypes[i] = inferredTypes[i].elementType ?? dynamicType;
     }
-    TypeParameterType elementTypeParam =
-        _typeProvider.setType.typeParameters[0].type;
-    ParameterElementImpl syntheticElementParameter =
-        new ParameterElementImpl.synthetic(
-            'key', elementTypeParam, ParameterKind.POSITIONAL);
-    List<ParameterElement> parameters = new List.filled(
-        elementTypes.length, syntheticElementParameter,
-        growable: true);
-    return (_typeSystem as Dart2TypeSystem).inferGenericFunctionOrType(
-        _typeProvider.setType, parameters, elementTypes, contextType,
-        isConst: node.isConst,
-        errorReporter: _resolver.errorReporter,
-        errorNode: node);
+
+    var typeArguments = _typeSystem.inferGenericFunctionOrType(
+      typeParameters: typeParameters,
+      parameters: parameters,
+      declaredReturnType: element.thisType,
+      argumentTypes: argumentTypes,
+      contextReturnType: contextType,
+    );
+    return element.instantiate(
+      typeArguments: typeArguments,
+      nullabilitySuffix: _noneOrStarSuffix,
+    );
   }
 
   /**
@@ -2182,13 +2223,10 @@
       return _hasNullShorting(node.leftHandSide);
     }
     if (node is IndexExpression) {
-      return node.leftBracket.type ==
-              TokenType.QUESTION_PERIOD_OPEN_SQUARE_BRACKET ||
-          _hasNullShorting(node.target);
+      return node.isNullAware || _hasNullShorting(node.target);
     }
     if (node is PropertyAccess) {
-      return node.operator.type == TokenType.QUESTION_PERIOD ||
-          _hasNullShorting(node.target);
+      return node.isNullAware || _hasNullShorting(node.target);
     }
     return false;
   }
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 a7d934a..f6687b4 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
@@ -777,10 +777,11 @@
           [List<Combinator> combinators]) =>
       importDirective(null, uri, false, prefix, combinators);
 
-  static IndexExpression indexExpression(Expression array, Expression index) =>
+  static IndexExpression indexExpression(Expression array, Expression index,
+          [TokenType leftBracket = TokenType.OPEN_SQUARE_BRACKET]) =>
       astFactory.indexExpressionForTarget(
           array,
-          TokenFactory.tokenFromType(TokenType.OPEN_SQUARE_BRACKET),
+          TokenFactory.tokenFromType(leftBracket),
           index,
           TokenFactory.tokenFromType(TokenType.CLOSE_SQUARE_BRACKET));
 
diff --git a/pkg/analyzer/lib/src/generated/testing/element_factory.dart b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
index c0ea183..0ed4131 100644
--- a/pkg/analyzer/lib/src/generated/testing/element_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
@@ -170,7 +170,7 @@
     FieldElementImpl valuesField = new FieldElementImpl("values", -1);
     valuesField.isStatic = true;
     valuesField.isConst = true;
-    valuesField.type = typeProvider.listType.instantiate(<DartType>[enumType]);
+    valuesField.type = typeProvider.listType2(enumType);
     fields.add(valuesField);
     //
     // Build the enum constants.
@@ -404,7 +404,6 @@
     element.function = new GenericFunctionTypeElementImpl.forOffset(-1)
       ..parameters = parameters
       ..returnType = returnType ?? DynamicTypeImpl.instance;
-    element.type = new FunctionTypeImpl.forTypedef(element);
     return element;
   }
 
@@ -586,6 +585,7 @@
     setter.parameters = <ParameterElement>[parameter];
     setter.returnType = VoidTypeImpl.instance;
     setter.type = new FunctionTypeImpl(setter);
+    setter.isStatic = isStatic;
     field.setter = setter;
     return setter;
   }
@@ -628,9 +628,7 @@
   }
 
   static TypeParameterElementImpl typeParameterElement(String name) {
-    TypeParameterElementImpl element = new TypeParameterElementImpl(name, 0);
-    element.type = new TypeParameterTypeImpl(element);
-    return element;
+    return new TypeParameterElementImpl(name, 0);
   }
 
   static List<TypeParameterElement> typeParameters(List<String> names) {
@@ -649,7 +647,6 @@
   static TypeParameterElementImpl typeParameterWithType(String name,
       [DartType bound]) {
     TypeParameterElementImpl typeParameter = typeParameterElement(name);
-    typeParameter.type = new TypeParameterTypeImpl(typeParameter);
     typeParameter.bound = bound;
     return typeParameter;
   }
diff --git a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
index 5d27b81..9538549 100644
--- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
+++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
 import 'package:analyzer/src/generated/source.dart' show Source;
@@ -23,13 +23,17 @@
     context ??= _MockAnalysisContext();
     var sdkElements = MockSdkElements(context, nullabilitySuffix);
     return TestTypeProvider._(
+      nullabilitySuffix,
       sdkElements.coreLibrary,
       sdkElements.asyncLibrary,
     );
   }
 
-  TestTypeProvider._(LibraryElement coreLibrary, LibraryElement asyncLibrary)
-      : super(coreLibrary, asyncLibrary);
+  TestTypeProvider._(
+    NullabilitySuffix nullabilitySuffix,
+    LibraryElement coreLibrary,
+    LibraryElement asyncLibrary,
+  ) : super(coreLibrary, asyncLibrary, nullabilitySuffix: nullabilitySuffix);
 }
 
 class _MockAnalysisContext implements AnalysisContext {
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 85a737b..5f384f0 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -6,9 +6,10 @@
 import 'dart:math' as math;
 
 import 'package:analyzer/dart/analysis/features.dart';
-import 'package:analyzer/dart/ast/ast.dart' show AstNode;
+import 'package:analyzer/dart/ast/ast.dart' show AstNode, ConstructorName;
 import 'package:analyzer/dart/ast/token.dart' show Keyword, TokenType;
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_system.dart' as public;
 import 'package:analyzer/error/listener.dart' show ErrorReporter;
@@ -17,7 +18,7 @@
 import 'package:analyzer/src/dart/element/member.dart' show TypeParameterMember;
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
-import 'package:analyzer/src/error/codes.dart' show StrongModeCode;
+import 'package:analyzer/src/error/codes.dart' show HintCode, StrongModeCode;
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisContext, AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
@@ -106,9 +107,15 @@
    */
   final bool implicitCasts;
 
+  /// A flag indicating whether inference failures are allowed, off by default.
+  ///
+  /// This option is experimental and subject to change.
+  final bool strictInference;
+
   final TypeProvider typeProvider;
 
-  Dart2TypeSystem(this.typeProvider, {this.implicitCasts: true});
+  Dart2TypeSystem(this.typeProvider,
+      {this.implicitCasts: true, this.strictInference: false});
 
   /// Returns true iff the type [t] accepts function types, and requires an
   /// implicit coercion if interface types with a `call` method are passed in.
@@ -202,7 +209,7 @@
    * Given a generic function type `F<T0, T1, ... Tn>` and a context type C,
    * infer an instantiation of F, such that `F<S0, S1, ..., Sn>` <: C.
    *
-   * This is similar to [inferGenericFunctionOrType2], but the return type is
+   * This is similar to [inferGenericFunctionOrType], but the return type is
    * also considered as part of the solution.
    *
    * If this function is called with a [contextType] that is also
@@ -231,49 +238,6 @@
     );
   }
 
-  /// Infers a generic type, function, method, or list/map literal
-  /// instantiation, using the downward context type as well as the argument
-  /// types if available.
-  ///
-  /// For example, given a function type with generic type parameters, this
-  /// infers the type parameters from the actual argument types, and returns the
-  /// instantiated function type.
-  ///
-  /// Concretely, given a function type with parameter types P0, P1, ... Pn,
-  /// result type R, and generic type parameters T0, T1, ... Tm, use the
-  /// argument types A0, A1, ... An to solve for the type parameters.
-  ///
-  /// For each parameter Pi, we want to ensure that Ai <: Pi. We can do this by
-  /// running the subtype algorithm, and when we reach a type parameter Tj,
-  /// recording the lower or upper bound it must satisfy. At the end, all
-  /// constraints can be combined to determine the type.
-  ///
-  /// All constraints on each type parameter Tj are tracked, as well as where
-  /// they originated, so we can issue an error message tracing back to the
-  /// argument values, type parameter "extends" clause, or the return type
-  /// context.
-  T inferGenericFunctionOrType<T extends ParameterizedType>(
-      T genericType,
-      List<ParameterElement> parameters,
-      List<DartType> argumentTypes,
-      DartType returnContextType,
-      {ErrorReporter errorReporter,
-      AstNode errorNode,
-      bool downwards: false,
-      bool isConst: false}) {
-    var inferredTypes = inferGenericFunctionOrType2(
-      genericType,
-      parameters,
-      argumentTypes,
-      returnContextType,
-      errorReporter: errorReporter,
-      errorNode: errorNode,
-      downwards: downwards,
-      isConst: isConst,
-    );
-    return genericType.instantiate(inferredTypes);
-  }
-
   /// Infers type arguments for a generic type, function, method, or
   /// list/map literal, using the downward context type as well as the
   /// argument types if available.
@@ -295,18 +259,19 @@
   /// they originated, so we can issue an error message tracing back to the
   /// argument values, type parameter "extends" clause, or the return type
   /// context.
-  List<DartType> inferGenericFunctionOrType2<T extends ParameterizedType>(
-      T genericType,
-      List<ParameterElement> parameters,
-      List<DartType> argumentTypes,
-      DartType returnContextType,
-      {ErrorReporter errorReporter,
-      AstNode errorNode,
-      bool downwards: false,
-      bool isConst: false}) {
-    // TODO(jmesserly): expose typeFormals on ParameterizedType.
-    List<TypeParameterElement> typeFormals = typeFormalsAsElements(genericType);
-    if (typeFormals.isEmpty) {
+  List<DartType> inferGenericFunctionOrType({
+    ClassElement genericClass,
+    @required List<TypeParameterElement> typeParameters,
+    @required List<ParameterElement> parameters,
+    @required DartType declaredReturnType,
+    @required List<DartType> argumentTypes,
+    @required DartType contextReturnType,
+    ErrorReporter errorReporter,
+    AstNode errorNode,
+    bool downwards: false,
+    bool isConst: false,
+  }) {
+    if (typeParameters.isEmpty) {
       return null;
     }
 
@@ -314,30 +279,32 @@
     // inferred. It will optimistically assume these type parameters can be
     // subtypes (or supertypes) as necessary, and track the constraints that
     // are implied by this.
-    var inferrer = new GenericInferrer(typeProvider, this, typeFormals);
+    var inferrer = new GenericInferrer(typeProvider, this, typeParameters);
 
-    DartType declaredReturnType =
-        genericType is FunctionType ? genericType.returnType : genericType;
-
-    if (returnContextType != null) {
+    if (contextReturnType != null) {
       if (isConst) {
-        returnContextType = _eliminateTypeVariables(returnContextType);
+        contextReturnType = _eliminateTypeVariables(contextReturnType);
       }
-      inferrer.constrainReturnType(declaredReturnType, returnContextType);
+      inferrer.constrainReturnType(declaredReturnType, contextReturnType);
     }
 
     for (int i = 0; i < argumentTypes.length; i++) {
       // Try to pass each argument to each parameter, recording any type
       // parameter bounds that were implied by this assignment.
       inferrer.constrainArgument(
-          argumentTypes[i], parameters[i].type, parameters[i].name,
-          genericType: genericType);
+        argumentTypes[i],
+        parameters[i].type,
+        parameters[i].name,
+        genericClass: genericClass,
+      );
     }
 
-    return inferrer.infer(typeFormals,
-        errorReporter: errorReporter,
-        errorNode: errorNode,
-        downwardsInferPhase: downwards);
+    return inferrer.infer(
+      typeParameters,
+      errorReporter: errorReporter,
+      errorNode: errorNode,
+      downwardsInferPhase: downwards,
+    );
   }
 
   /**
@@ -351,7 +318,7 @@
    * and generic functions; compute lazily and cache.
    */
   DartType instantiateToBounds(DartType type,
-      {List<bool> hasError, Map<TypeParameterType, DartType> knownTypes}) {
+      {List<bool> hasError, Map<TypeParameterElement, DartType> knownTypes}) {
     List<TypeParameterElement> typeFormals = typeFormalsAsElements(type);
     List<DartType> arguments = instantiateTypeFormalsToBounds(typeFormals,
         hasError: hasError, knownTypes: knownTypes);
@@ -371,20 +338,19 @@
   List<DartType> instantiateTypeFormalsToBounds(
       List<TypeParameterElement> typeFormals,
       {List<bool> hasError,
-      Map<TypeParameterType, DartType> knownTypes}) {
+      Map<TypeParameterElement, DartType> knownTypes}) {
     int count = typeFormals.length;
     if (count == 0) {
       return const <DartType>[];
     }
 
-    Set<TypeParameterType> all = new Set<TypeParameterType>();
+    Set<TypeParameterElement> all = new Set<TypeParameterElement>();
     // all ground
-    Map<TypeParameterType, DartType> defaults = knownTypes ?? {};
+    Map<TypeParameterElement, DartType> defaults = knownTypes ?? {};
     // not ground
-    Map<TypeParameterType, DartType> partials = {};
+    Map<TypeParameterElement, DartType> partials = {};
 
-    for (TypeParameterElement typeParameterElement in typeFormals) {
-      TypeParameterType typeParameter = typeParameterElement.type;
+    for (TypeParameterElement typeParameter in typeFormals) {
       all.add(typeParameter);
       if (!defaults.containsKey(typeParameter)) {
         if (typeParameter.bound == null) {
@@ -395,8 +361,8 @@
       }
     }
 
-    List<TypeParameterType> getFreeParameters(DartType rootType) {
-      List<TypeParameterType> parameters = null;
+    List<TypeParameterElement> getFreeParameters(DartType rootType) {
+      List<TypeParameterElement> parameters = null;
       Set<DartType> visitedTypes = new HashSet<DartType>();
 
       void appendParameters(DartType type) {
@@ -407,9 +373,12 @@
           return;
         }
         visitedTypes.add(type);
-        if (type is TypeParameterType && all.contains(type)) {
-          parameters ??= <TypeParameterType>[];
-          parameters.add(type);
+        if (type is TypeParameterType) {
+          var element = type.element;
+          if (all.contains(element)) {
+            parameters ??= <TypeParameterElement>[];
+            parameters.add(element);
+          }
         } else if (AnalysisDriver.useSummary2) {
           if (type is FunctionType) {
             appendParameters(type.returnType);
@@ -429,17 +398,17 @@
     bool hasProgress = true;
     while (hasProgress) {
       hasProgress = false;
-      for (TypeParameterType parameter in partials.keys) {
+      for (TypeParameterElement parameter in partials.keys) {
         DartType value = partials[parameter];
-        List<TypeParameterType> freeParameters = getFreeParameters(value);
+        List<TypeParameterElement> freeParameters = getFreeParameters(value);
         if (freeParameters == null) {
           defaults[parameter] = value;
           partials.remove(parameter);
           hasProgress = true;
           break;
         } else if (freeParameters.every(defaults.containsKey)) {
-          defaults[parameter] = value.substitute2(
-              defaults.values.toList(), defaults.keys.toList());
+          defaults[parameter] =
+              Substitution.fromMap(defaults).substituteType(value);
           partials.remove(parameter);
           hasProgress = true;
           break;
@@ -459,19 +428,20 @@
       var range = defaults.values.toList();
       // Build a substitution Phi mapping each uncompleted type variable to
       // dynamic, and each completed type variable to its default.
-      for (TypeParameterType parameter in partials.keys) {
+      for (TypeParameterElement parameter in partials.keys) {
         domain.add(parameter);
         range.add(DynamicTypeImpl.instance);
       }
       // Set the default for an uncompleted type variable (T extends B)
       // to be Phi(B)
-      for (TypeParameterType parameter in partials.keys) {
-        defaults[parameter] = partials[parameter].substitute2(range, domain);
+      for (TypeParameterElement parameter in partials.keys) {
+        defaults[parameter] = Substitution.fromPairs(domain, range)
+            .substituteType(partials[parameter]);
       }
     }
 
     List<DartType> orderedArguments =
-        typeFormals.map((p) => defaults[p.type]).toList();
+        typeFormals.map((p) => defaults[p]).toList();
     return orderedArguments;
   }
 
@@ -705,7 +675,7 @@
 
       // given t1 is Future<A> | A, then:
       // (Future<A> | A) <: t2 iff Future<A> <: t2 and A <: t2.
-      var t1Future = typeProvider.futureType.instantiate([t1TypeArg]);
+      var t1Future = typeProvider.futureType2(t1TypeArg);
       return isSubtypeOf(t1Future, t2) && isSubtypeOf(t1TypeArg, t2);
     }
 
@@ -713,7 +683,7 @@
       // 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.futureType.instantiate([t2TypeArg]);
+      var t2Future = typeProvider.futureType2(t2TypeArg);
       return isSubtypeOf(t1, t2Future) || isSubtypeOf(t1, t2TypeArg);
     }
 
@@ -1250,7 +1220,7 @@
 class GenericInferrer {
   final Dart2TypeSystem _typeSystem;
   final TypeProvider typeProvider;
-  final Map<TypeParameterElement, List<_TypeConstraint>> constraints;
+  final Map<TypeParameterElement, List<_TypeConstraint>> constraints = {};
 
   /// Buffer recording constraints recorded while performing a recursive call to
   /// [_matchSubtypeOf] that might fail, so that any constraints recorded during
@@ -1258,10 +1228,7 @@
   final _undoBuffer = <_TypeConstraint>[];
 
   GenericInferrer(this.typeProvider, this._typeSystem,
-      Iterable<TypeParameterElement> typeFormals)
-      : constraints = new HashMap(
-            equals: (x, y) => x.location == y.location,
-            hashCode: (x) => x.location.hashCode) {
+      Iterable<TypeParameterElement> typeFormals) {
     for (var formal in typeFormals) {
       constraints[formal] = [];
     }
@@ -1271,10 +1238,10 @@
   /// is a subtype of the [parameterType].
   void constrainArgument(
       DartType argumentType, DartType parameterType, String parameterName,
-      {DartType genericType}) {
+      {ClassElement genericClass}) {
     var origin = new _TypeConstraintFromArgument(
         argumentType, parameterType, parameterName,
-        genericType: genericType);
+        genericClass: genericClass);
     tryMatchSubtypeOf(argumentType, parameterType, origin, covariant: false);
   }
 
@@ -1313,30 +1280,29 @@
       AstNode errorNode,
       bool failAtError: false,
       bool downwardsInferPhase: false}) {
-    var fnTypeParams = TypeParameterTypeImpl.getTypes(typeFormals);
-
     // Initialize the inferred type array.
     //
     // In the downwards phase, they all start as `?` to offer reasonable
     // degradation for f-bounded type parameters.
     var inferredTypes = new List<DartType>.filled(
-        fnTypeParams.length, UnknownInferredType.instance);
+        typeFormals.length, UnknownInferredType.instance);
     var _inferTypeParameter = downwardsInferPhase
         ? _inferTypeParameterFromContext
         : _inferTypeParameterFromAll;
 
-    for (int i = 0; i < fnTypeParams.length; i++) {
-      TypeParameterType typeParam = fnTypeParams[i];
+    for (int i = 0; i < typeFormals.length; i++) {
+      TypeParameterElement typeParam = typeFormals[i];
 
-      var typeParamBound = typeParam.bound;
       _TypeConstraint extendsClause;
-      if (considerExtendsClause && !typeParamBound.isDynamic) {
-        extendsClause = new _TypeConstraint.fromExtends(typeParam,
-            typeParam.bound.substitute2(inferredTypes, fnTypeParams));
+      if (considerExtendsClause && typeParam.bound != null) {
+        extendsClause = new _TypeConstraint.fromExtends(
+            typeParam,
+            Substitution.fromPairs(typeFormals, inferredTypes)
+                .substituteType(typeParam.bound));
       }
 
       inferredTypes[i] =
-          _inferTypeParameter(constraints[typeParam.element], extendsClause);
+          _inferTypeParameter(constraints[typeParam], extendsClause);
     }
 
     // If the downwards infer phase has failed, we'll catch this in the upwards
@@ -1346,14 +1312,14 @@
     }
 
     // Check the inferred types against all of the constraints.
-    var knownTypes = new HashMap<TypeParameterType, DartType>(
-        equals: (x, y) => x.element == y.element,
-        hashCode: (x) => x.element.hashCode);
-    for (int i = 0; i < fnTypeParams.length; i++) {
-      TypeParameterType typeParam = fnTypeParams[i];
-      var constraints = this.constraints[typeParam.element];
-      var typeParamBound =
-          typeParam.bound.substitute2(inferredTypes, fnTypeParams);
+    var knownTypes = <TypeParameterElement, DartType>{};
+    for (int i = 0; i < typeFormals.length; i++) {
+      TypeParameterElement typeParam = typeFormals[i];
+      var constraints = this.constraints[typeParam];
+      var typeParamBound = typeParam.bound != null
+          ? Substitution.fromPairs(typeFormals, inferredTypes)
+              .substituteType(typeParam.bound)
+          : typeProvider.dynamicType;
 
       var inferred = inferredTypes[i];
       bool success =
@@ -1371,7 +1337,7 @@
         errorReporter?.reportErrorForNode(
             StrongModeCode.COULD_NOT_INFER,
             errorNode,
-            [typeParam, _formatError(typeParam, inferred, constraints)]);
+            [typeParam.name, _formatError(typeParam, inferred, constraints)]);
 
         // Heuristic: even if we failed, keep the erroneous type.
         // It should satisfy at least some of the constraints (e.g. the return
@@ -1383,7 +1349,7 @@
         if (failAtError) return null;
         errorReporter
             ?.reportErrorForNode(StrongModeCode.COULD_NOT_INFER, errorNode, [
-          typeParam,
+          typeParam.name,
           ' Inferred candidate type $inferred has type parameters'
               ' ${(inferred as FunctionType).typeFormals}, but a function with'
               ' type parameters cannot be used as a type argument.'
@@ -1398,11 +1364,25 @@
 
       if (UnknownInferredType.isKnown(inferred)) {
         knownTypes[typeParam] = inferred;
+      } else if (_typeSystem.strictInference) {
+        // [typeParam] could not be inferred. A result will still be returned
+        // by [infer], with [typeParam] filled in as its bounds. This is
+        // considered a failure of inference, under the "strict-inference"
+        // mode.
+        if (errorNode is ConstructorName) {
+          String constructorName = '${errorNode.type}.${errorNode.name}';
+          errorReporter?.reportTypeErrorForNode(
+              HintCode.INFERENCE_FAILURE_ON_INSTANCE_CREATION,
+              errorNode,
+              [constructorName]);
+        }
+        // TODO(srawlins): More inference failure cases, like functions, and
+        // function expressions.
       }
     }
 
     // Use instantiate to bounds to finish things off.
-    var hasError = new List<bool>.filled(fnTypeParams.length, false);
+    var hasError = new List<bool>.filled(typeFormals.length, false);
     var result = _typeSystem.instantiateTypeFormalsToBounds(typeFormals,
         hasError: hasError, knownTypes: knownTypes);
 
@@ -1410,13 +1390,13 @@
     for (int i = 0; i < hasError.length; i++) {
       if (hasError[i]) {
         if (failAtError) return null;
-        TypeParameterType typeParam = fnTypeParams[i];
-        var typeParamBound =
-            typeParam.bound.substitute2(inferredTypes, fnTypeParams);
+        TypeParameterElement typeParam = typeFormals[i];
+        var typeParamBound = Substitution.fromPairs(typeFormals, inferredTypes)
+            .substituteType(typeParam.bound ?? typeProvider.objectType);
         // TODO(jmesserly): improve this error message.
         errorReporter
             ?.reportErrorForNode(StrongModeCode.COULD_NOT_INFER, errorNode, [
-          typeParam,
+          typeParam.name,
           "\nRecursive bound cannot be instantiated: '$typeParamBound'."
               "\nConsider passing explicit type argument(s) "
               "to the generic.\n\n'"
@@ -1504,9 +1484,9 @@
     return lower;
   }
 
-  String _formatError(TypeParameterType typeParam, DartType inferred,
+  String _formatError(TypeParameterElement typeParam, DartType inferred,
       Iterable<_TypeConstraint> constraints) {
-    var intro = "Tried to infer '$inferred' for '$typeParam'"
+    var intro = "Tried to infer '$inferred' for '${typeParam.name}'"
         " which doesn't work:";
 
     var constraintsByOrigin = <_TypeConstraintOrigin, List<_TypeConstraint>>{};
@@ -1552,14 +1532,14 @@
           //  GLB(FutureOr<A>, FutureOr<B>) == FutureOr<GLB(A, B)>
           if (t2.isDartAsyncFutureOr) {
             var t2TypeArg = t2.typeArguments[0];
-            return typeProvider.futureOrType
-                .instantiate([_getGreatestLowerBound(t1TypeArg, t2TypeArg)]);
+            return typeProvider
+                .futureOrType2(_getGreatestLowerBound(t1TypeArg, t2TypeArg));
           }
           // GLB(FutureOr<A>, Future<B>) == Future<GLB(A, B)>
           if (t2.isDartAsyncFuture) {
             var t2TypeArg = t2.typeArguments[0];
-            return typeProvider.futureType
-                .instantiate([_getGreatestLowerBound(t1TypeArg, t2TypeArg)]);
+            return typeProvider
+                .futureType2(_getGreatestLowerBound(t1TypeArg, t2TypeArg));
           }
         }
         // GLB(FutureOr<A>, B) == GLB(A, B)
@@ -1699,7 +1679,7 @@
       var constraints = this.constraints[t1.element];
       if (constraints != null) {
         if (!identical(t2, UnknownInferredType.instance)) {
-          var constraint = new _TypeConstraint(origin, t1, upper: t2);
+          var constraint = new _TypeConstraint(origin, t1.element, upper: t2);
           constraints.add(constraint);
           _undoBuffer.add(constraint);
         }
@@ -1710,7 +1690,7 @@
       var constraints = this.constraints[t2.element];
       if (constraints != null) {
         if (!identical(t1, UnknownInferredType.instance)) {
-          var constraint = new _TypeConstraint(origin, t2, lower: t1);
+          var constraint = new _TypeConstraint(origin, t2.element, lower: t1);
           constraints.add(constraint);
           _undoBuffer.add(constraint);
         }
@@ -1738,7 +1718,7 @@
 
       // given t1 is Future<A> | A, then:
       // (Future<A> | A) <: t2 iff Future<A> <: t2 and A <: t2.
-      var t1Future = typeProvider.futureType.instantiate([t1TypeArg]);
+      var t1Future = typeProvider.futureType2(t1TypeArg);
       return matchSubtype(t1Future, t2) && matchSubtype(t1TypeArg, t2);
     }
 
@@ -1746,7 +1726,7 @@
       // 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.futureType.instantiate([t2TypeArg]);
+      var t2Future = typeProvider.futureType2(t2TypeArg);
 
       // First we try matching `t1 <: Future<A>`.  If that succeeds *and*
       // records at least one constraint, then we proceed using that constraint.
@@ -1850,7 +1830,7 @@
   void _rewindConstraints(int previousRewindBufferLength) {
     while (_undoBuffer.length > previousRewindBufferLength) {
       var constraint = _undoBuffer.removeLast();
-      var element = constraint.typeParameter.element;
+      var element = constraint.typeParameter;
       assert(identical(constraints[element].last, constraint));
       constraints[element].removeLast();
     }
@@ -2874,7 +2854,8 @@
   static TypeSystem create(AnalysisContext context) {
     var options = context.analysisOptions as AnalysisOptionsImpl;
     return new Dart2TypeSystem(context.typeProvider,
-        implicitCasts: options.implicitCasts);
+        implicitCasts: options.implicitCasts,
+        strictInference: options.strictInference);
   }
 }
 
@@ -3003,7 +2984,7 @@
 /// A constraint on a type parameter that we're inferring.
 class _TypeConstraint extends _TypeRange {
   /// The type parameter that is constrained by [lowerBound] or [upperBound].
-  final TypeParameterType typeParameter;
+  final TypeParameterElement typeParameter;
 
   /// Where this constraint comes from, used for error messages.
   ///
@@ -3014,8 +2995,10 @@
       {DartType upper, DartType lower})
       : super(upper: upper, lower: lower);
 
-  _TypeConstraint.fromExtends(TypeParameterType type, DartType extendsType)
-      : this(new _TypeConstraintFromExtendsClause(type, extendsType), type,
+  _TypeConstraint.fromExtends(
+      TypeParameterElement element, DartType extendsType)
+      : this(
+            new _TypeConstraintFromExtendsClause(element, extendsType), element,
             upper: extendsType);
 
   bool get isDownwards => origin is! _TypeConstraintFromArgument;
@@ -3034,11 +3017,11 @@
   final DartType argumentType;
   final DartType parameterType;
   final String parameterName;
-  final DartType genericType;
+  final ClassElement genericClass;
 
   _TypeConstraintFromArgument(
       this.argumentType, this.parameterType, this.parameterName,
-      {this.genericType});
+      {this.genericClass});
 
   @override
   formatError() {
@@ -3046,14 +3029,14 @@
     // However in summary code it doesn't look like the AST node with span is
     // available.
     String prefix;
-    if (genericType != null &&
-        (genericType.name == "List" || genericType.name == "Map") &&
-        genericType?.element?.library?.isDartCore == true) {
+    if (genericClass != null &&
+        (genericClass.name == "List" || genericClass.name == "Map") &&
+        genericClass.library.isDartCore == true) {
       // This will become:
       //     "List element"
       //     "Map key"
       //     "Map value"
-      prefix = "${genericType.name} $parameterName";
+      prefix = "${genericClass.name} $parameterName";
     } else {
       prefix = "Parameter '$parameterName'";
     }
@@ -3067,7 +3050,7 @@
 }
 
 class _TypeConstraintFromExtendsClause extends _TypeConstraintOrigin {
-  final TypeParameterType typeParam;
+  final TypeParameterElement typeParam;
   final DartType extendsType;
 
   _TypeConstraintFromExtendsClause(this.typeParam, this.extendsType);
@@ -3075,7 +3058,7 @@
   @override
   formatError() {
     return [
-      "Type parameter '$typeParam'",
+      "Type parameter '${typeParam.name}'",
       "declared to extend '$extendsType'."
     ];
   }
diff --git a/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart b/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
index cfb7917..2e9c37f 100644
--- a/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
+++ b/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
@@ -246,8 +246,8 @@
     }
     Element element = node.staticElement;
     if (checkFutureAndStream &&
-        (element == _typeProvider.futureType.element ||
-            element == _typeProvider.streamType.element)) {
+        (element == _typeProvider.futureElement ||
+            element == _typeProvider.streamElement)) {
       for (LibraryElement importedLibrary
           in _containingLibrary.importedLibraries) {
         if (!importedLibrary.isDartCore) {
diff --git a/pkg/analyzer/lib/src/lint/analysis.dart b/pkg/analyzer/lib/src/lint/analysis.dart
index e3dae80..0ec27b9 100644
--- a/pkg/analyzer/lib/src/lint/analysis.dart
+++ b/pkg/analyzer/lib/src/lint/analysis.dart
@@ -18,7 +18,7 @@
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
 import 'package:analyzer/src/file_system/file_system.dart';
-import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
diff --git a/pkg/analyzer/lib/src/summary/expr_builder.dart b/pkg/analyzer/lib/src/summary/expr_builder.dart
index f34a7ba..ed9493b 100644
--- a/pkg/analyzer/lib/src/summary/expr_builder.dart
+++ b/pkg/analyzer/lib/src/summary/expr_builder.dart
@@ -895,7 +895,7 @@
     var typeArg = typeArguments == null
         ? resynthesizer.typeProvider.dynamicType
         : typeArguments.arguments[0].type;
-    var staticType = resynthesizer.typeProvider.listType.instantiate([typeArg]);
+    var staticType = resynthesizer.typeProvider.listType2(typeArg);
     _push(AstTestFactory.listLiteral2(Keyword.CONST, typeArguments, elements)
       ..staticType = staticType);
   }
@@ -960,8 +960,7 @@
     var valueType = typeArguments == null
         ? resynthesizer.typeProvider.dynamicType
         : typeArguments.arguments[1].type;
-    var staticType =
-        resynthesizer.typeProvider.mapType.instantiate([keyType, valueType]);
+    var staticType = resynthesizer.typeProvider.mapType2(keyType, valueType);
     SetOrMapLiteralImpl literal =
         AstTestFactory.setOrMapLiteral(Keyword.CONST, typeArguments, entries);
     literal.becomeMap();
@@ -1013,15 +1012,13 @@
       if (typeArguments.arguments.length == 2) {
         var keyType = typeArguments.arguments[0].type;
         var valueType = typeArguments.arguments[1].type;
-        staticType = resynthesizer.typeProvider.mapType
-            .instantiate([keyType, valueType]);
+        staticType = resynthesizer.typeProvider.mapType2(keyType, valueType);
       } else if (typeArguments.arguments.length == 1) {
         isMap = false;
         var valueType = typeArguments == null
             ? resynthesizer.typeProvider.dynamicType
             : typeArguments.arguments[0].type;
-        staticType =
-            resynthesizer.typeProvider.setType.instantiate([valueType]);
+        staticType = resynthesizer.typeProvider.setType2(valueType);
       }
     } else {
       for (var i = 0; i < elements.length; ++i) {
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index 00c787a..4260806 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -5022,6 +5022,7 @@
   double _variantField_21;
   LinkedNodeTypeBuilder _variantField_25;
   String _variantField_20;
+  List<LinkedNodeTypeBuilder> _variantField_39;
   int _flags;
   String _variantField_1;
   int _variantField_36;
@@ -5065,6 +5066,12 @@
   }
 
   @override
+  LinkedNodeTypeBuilder get extensionOverride_extendedType {
+    assert(kind == idl.LinkedNodeKind.extensionOverride);
+    return _variantField_24;
+  }
+
+  @override
   LinkedNodeTypeBuilder get invocationExpression_invokeType {
     assert(kind == idl.LinkedNodeKind.functionExpressionInvocation ||
         kind == idl.LinkedNodeKind.methodInvocation);
@@ -5094,6 +5101,11 @@
     _variantField_24 = value;
   }
 
+  set extensionOverride_extendedType(LinkedNodeTypeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.extensionOverride);
+    _variantField_24 = value;
+  }
+
   set invocationExpression_invokeType(LinkedNodeTypeBuilder value) {
     assert(kind == idl.LinkedNodeKind.functionExpressionInvocation ||
         kind == idl.LinkedNodeKind.methodInvocation);
@@ -5155,6 +5167,12 @@
   }
 
   @override
+  List<LinkedNodeBuilder> get extensionOverride_arguments {
+    assert(kind == idl.LinkedNodeKind.extensionOverride);
+    return _variantField_2 ??= <LinkedNodeBuilder>[];
+  }
+
+  @override
   List<LinkedNodeBuilder> get formalParameterList_parameters {
     assert(kind == idl.LinkedNodeKind.formalParameterList);
     return _variantField_2 ??= <LinkedNodeBuilder>[];
@@ -5297,6 +5315,11 @@
     _variantField_2 = value;
   }
 
+  set extensionOverride_arguments(List<LinkedNodeBuilder> value) {
+    assert(kind == idl.LinkedNodeKind.extensionOverride);
+    _variantField_2 = value;
+  }
+
   set formalParameterList_parameters(List<LinkedNodeBuilder> value) {
     assert(kind == idl.LinkedNodeKind.formalParameterList);
     _variantField_2 = value;
@@ -6419,6 +6442,12 @@
   }
 
   @override
+  LinkedNodeBuilder get extensionOverride_extensionName {
+    assert(kind == idl.LinkedNodeKind.extensionOverride);
+    return _variantField_7;
+  }
+
+  @override
   LinkedNodeBuilder get fieldFormalParameter_typeParameters {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
     return _variantField_7;
@@ -6677,6 +6706,11 @@
     _variantField_7 = value;
   }
 
+  set extensionOverride_extensionName(LinkedNodeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.extensionOverride);
+    _variantField_7 = value;
+  }
+
   set fieldFormalParameter_typeParameters(LinkedNodeBuilder value) {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
     _variantField_7 = value;
@@ -6890,6 +6924,12 @@
   }
 
   @override
+  LinkedNodeBuilder get extensionOverride_typeArguments {
+    assert(kind == idl.LinkedNodeKind.extensionOverride);
+    return _variantField_8;
+  }
+
+  @override
   LinkedNodeBuilder get fieldFormalParameter_formalParameters {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
     return _variantField_8;
@@ -6978,6 +7018,11 @@
     _variantField_8 = value;
   }
 
+  set extensionOverride_typeArguments(LinkedNodeBuilder value) {
+    assert(kind == idl.LinkedNodeKind.extensionOverride);
+    _variantField_8 = value;
+  }
+
   set fieldFormalParameter_formalParameters(LinkedNodeBuilder value) {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
     _variantField_8 = value;
@@ -7739,6 +7784,17 @@
   }
 
   @override
+  List<LinkedNodeTypeBuilder> get extensionOverride_typeArgumentTypes {
+    assert(kind == idl.LinkedNodeKind.extensionOverride);
+    return _variantField_39 ??= <LinkedNodeTypeBuilder>[];
+  }
+
+  set extensionOverride_typeArgumentTypes(List<LinkedNodeTypeBuilder> value) {
+    assert(kind == idl.LinkedNodeKind.extensionOverride);
+    _variantField_39 = value;
+  }
+
+  @override
   int get flags => _flags ??= 0;
 
   set flags(int value) {
@@ -8387,6 +8443,19 @@
         _variantField_20 = extensionDeclaration_refName,
         _variantField_36 = informativeId;
 
+  LinkedNodeBuilder.extensionOverride({
+    LinkedNodeTypeBuilder extensionOverride_extendedType,
+    List<LinkedNodeBuilder> extensionOverride_arguments,
+    LinkedNodeBuilder extensionOverride_extensionName,
+    LinkedNodeBuilder extensionOverride_typeArguments,
+    List<LinkedNodeTypeBuilder> extensionOverride_typeArgumentTypes,
+  })  : _kind = idl.LinkedNodeKind.extensionOverride,
+        _variantField_24 = extensionOverride_extendedType,
+        _variantField_2 = extensionOverride_arguments,
+        _variantField_7 = extensionOverride_extensionName,
+        _variantField_8 = extensionOverride_typeArguments,
+        _variantField_39 = extensionOverride_typeArgumentTypes;
+
   LinkedNodeBuilder.fieldDeclaration({
     List<LinkedNodeBuilder> annotatedNode_metadata,
     LinkedNodeBuilder fieldDeclaration_fields,
@@ -9245,6 +9314,12 @@
       extensionDeclaration_extendedType?.flushInformative();
       extensionDeclaration_members?.forEach((b) => b.flushInformative());
       informativeId = null;
+    } else if (kind == idl.LinkedNodeKind.extensionOverride) {
+      extensionOverride_extendedType?.flushInformative();
+      extensionOverride_arguments?.forEach((b) => b.flushInformative());
+      extensionOverride_extensionName?.flushInformative();
+      extensionOverride_typeArguments?.flushInformative();
+      extensionOverride_typeArgumentTypes?.forEach((b) => b.flushInformative());
     } else if (kind == idl.LinkedNodeKind.fieldDeclaration) {
       annotatedNode_metadata?.forEach((b) => b.flushInformative());
       fieldDeclaration_fields?.flushInformative();
@@ -10056,6 +10131,32 @@
       signature.addInt(this.flags ?? 0);
       signature.addString(this.extensionDeclaration_refName ?? '');
       signature.addString(this.name ?? '');
+    } else if (kind == idl.LinkedNodeKind.extensionOverride) {
+      signature.addInt(this.kind == null ? 0 : this.kind.index);
+      if (this.extensionOverride_arguments == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.extensionOverride_arguments.length);
+        for (var x in this.extensionOverride_arguments) {
+          x?.collectApiSignature(signature);
+        }
+      }
+      signature.addBool(this.extensionOverride_extensionName != null);
+      this.extensionOverride_extensionName?.collectApiSignature(signature);
+      signature.addBool(this.extensionOverride_typeArguments != null);
+      this.extensionOverride_typeArguments?.collectApiSignature(signature);
+      signature.addInt(this.flags ?? 0);
+      signature.addBool(this.extensionOverride_extendedType != null);
+      this.extensionOverride_extendedType?.collectApiSignature(signature);
+      signature.addString(this.name ?? '');
+      if (this.extensionOverride_typeArgumentTypes == null) {
+        signature.addInt(0);
+      } else {
+        signature.addInt(this.extensionOverride_typeArgumentTypes.length);
+        for (var x in this.extensionOverride_typeArgumentTypes) {
+          x?.collectApiSignature(signature);
+        }
+      }
     } else if (kind == idl.LinkedNodeKind.fieldDeclaration) {
       signature.addInt(this.kind == null ? 0 : this.kind.index);
       if (this.annotatedNode_metadata == null) {
@@ -11146,6 +11247,7 @@
     fb.Offset offset_variantField_10;
     fb.Offset offset_variantField_25;
     fb.Offset offset_variantField_20;
+    fb.Offset offset_variantField_39;
     fb.Offset offset_variantField_1;
     fb.Offset offset_variantField_30;
     fb.Offset offset_variantField_14;
@@ -11208,6 +11310,10 @@
     if (_variantField_20 != null) {
       offset_variantField_20 = fbBuilder.writeString(_variantField_20);
     }
+    if (!(_variantField_39 == null || _variantField_39.isEmpty)) {
+      offset_variantField_39 = fbBuilder
+          .writeList(_variantField_39.map((b) => b.finish(fbBuilder)).toList());
+    }
     if (_variantField_1 != null) {
       offset_variantField_1 = fbBuilder.writeString(_variantField_1);
     }
@@ -11310,6 +11416,9 @@
     if (offset_variantField_20 != null) {
       fbBuilder.addOffset(20, offset_variantField_20);
     }
+    if (offset_variantField_39 != null) {
+      fbBuilder.addOffset(39, offset_variantField_39);
+    }
     if (_flags != null && _flags != 0) {
       fbBuilder.addUint32(18, _flags);
     }
@@ -11402,6 +11511,7 @@
   double _variantField_21;
   idl.LinkedNodeType _variantField_25;
   String _variantField_20;
+  List<idl.LinkedNodeType> _variantField_39;
   int _flags;
   String _variantField_1;
   int _variantField_36;
@@ -11451,6 +11561,14 @@
   }
 
   @override
+  idl.LinkedNodeType get extensionOverride_extendedType {
+    assert(kind == idl.LinkedNodeKind.extensionOverride);
+    _variantField_24 ??=
+        const _LinkedNodeTypeReader().vTableGet(_bc, _bcOffset, 24, null);
+    return _variantField_24;
+  }
+
+  @override
   idl.LinkedNodeType get invocationExpression_invokeType {
     assert(kind == idl.LinkedNodeKind.functionExpressionInvocation ||
         kind == idl.LinkedNodeKind.methodInvocation);
@@ -11541,6 +11659,15 @@
   }
 
   @override
+  List<idl.LinkedNode> get extensionOverride_arguments {
+    assert(kind == idl.LinkedNodeKind.extensionOverride);
+    _variantField_2 ??=
+        const fb.ListReader<idl.LinkedNode>(const _LinkedNodeReader())
+            .vTableGet(_bc, _bcOffset, 2, const <idl.LinkedNode>[]);
+    return _variantField_2;
+  }
+
+  @override
   List<idl.LinkedNode> get formalParameterList_parameters {
     assert(kind == idl.LinkedNodeKind.formalParameterList);
     _variantField_2 ??=
@@ -12494,6 +12621,14 @@
   }
 
   @override
+  idl.LinkedNode get extensionOverride_extensionName {
+    assert(kind == idl.LinkedNodeKind.extensionOverride);
+    _variantField_7 ??=
+        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 7, null);
+    return _variantField_7;
+  }
+
+  @override
   idl.LinkedNode get fieldFormalParameter_typeParameters {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
     _variantField_7 ??=
@@ -12798,6 +12933,14 @@
   }
 
   @override
+  idl.LinkedNode get extensionOverride_typeArguments {
+    assert(kind == idl.LinkedNodeKind.extensionOverride);
+    _variantField_8 ??=
+        const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 8, null);
+    return _variantField_8;
+  }
+
+  @override
   idl.LinkedNode get fieldFormalParameter_formalParameters {
     assert(kind == idl.LinkedNodeKind.fieldFormalParameter);
     _variantField_8 ??=
@@ -13373,6 +13516,15 @@
   }
 
   @override
+  List<idl.LinkedNodeType> get extensionOverride_typeArgumentTypes {
+    assert(kind == idl.LinkedNodeKind.extensionOverride);
+    _variantField_39 ??=
+        const fb.ListReader<idl.LinkedNodeType>(const _LinkedNodeTypeReader())
+            .vTableGet(_bc, _bcOffset, 39, const <idl.LinkedNodeType>[]);
+    return _variantField_39;
+  }
+
+  @override
   int get flags {
     _flags ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 18, 0);
     return _flags;
@@ -13970,6 +14122,26 @@
         _result["extensionDeclaration_refName"] = extensionDeclaration_refName;
       if (informativeId != 0) _result["informativeId"] = informativeId;
     }
+    if (kind == idl.LinkedNodeKind.extensionOverride) {
+      if (extensionOverride_extendedType != null)
+        _result["extensionOverride_extendedType"] =
+            extensionOverride_extendedType.toJson();
+      if (extensionOverride_arguments.isNotEmpty)
+        _result["extensionOverride_arguments"] = extensionOverride_arguments
+            .map((_value) => _value.toJson())
+            .toList();
+      if (extensionOverride_extensionName != null)
+        _result["extensionOverride_extensionName"] =
+            extensionOverride_extensionName.toJson();
+      if (extensionOverride_typeArguments != null)
+        _result["extensionOverride_typeArguments"] =
+            extensionOverride_typeArguments.toJson();
+      if (extensionOverride_typeArgumentTypes.isNotEmpty)
+        _result["extensionOverride_typeArgumentTypes"] =
+            extensionOverride_typeArgumentTypes
+                .map((_value) => _value.toJson())
+                .toList();
+    }
     if (kind == idl.LinkedNodeKind.fieldDeclaration) {
       if (annotatedNode_metadata.isNotEmpty)
         _result["annotatedNode_metadata"] =
@@ -15151,6 +15323,19 @@
         "name": name,
       };
     }
+    if (kind == idl.LinkedNodeKind.extensionOverride) {
+      return {
+        "extensionOverride_extendedType": extensionOverride_extendedType,
+        "extensionOverride_arguments": extensionOverride_arguments,
+        "extensionOverride_extensionName": extensionOverride_extensionName,
+        "extensionOverride_typeArguments": extensionOverride_typeArguments,
+        "extensionOverride_typeArgumentTypes":
+            extensionOverride_typeArgumentTypes,
+        "flags": flags,
+        "kind": kind,
+        "name": name,
+      };
+    }
     if (kind == idl.LinkedNodeKind.fieldDeclaration) {
       return {
         "annotatedNode_metadata": annotatedNode_metadata,
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index 4ce0eca..25ebd97 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -429,7 +429,9 @@
 
   withClause,
 
-  yieldStatement
+  yieldStatement,
+
+  extensionOverride
 }
 
 /// Kinds of [LinkedNodeType]s.
@@ -1961,6 +1963,8 @@
 
   variantField_20:string (id: 20);
 
+  variantField_39:[LinkedNodeType] (id: 39);
+
   flags:uint (id: 18);
 
   variantField_1:string (id: 1);
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index 0ada341..de1760a 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -1189,6 +1189,21 @@
   @VariantId(6, variant: LinkedNodeKind.extensionDeclaration)
   LinkedNode get extensionDeclaration_typeParameters;
 
+  @VariantId(2, variant: LinkedNodeKind.extensionOverride)
+  List<LinkedNode> get extensionOverride_arguments;
+
+  @VariantId(24, variant: LinkedNodeKind.extensionOverride)
+  LinkedNodeType get extensionOverride_extendedType;
+
+  @VariantId(7, variant: LinkedNodeKind.extensionOverride)
+  LinkedNode get extensionOverride_extensionName;
+
+  @VariantId(8, variant: LinkedNodeKind.extensionOverride)
+  LinkedNode get extensionOverride_typeArguments;
+
+  @VariantId(39, variant: LinkedNodeKind.extensionOverride)
+  List<LinkedNodeType> get extensionOverride_typeArgumentTypes;
+
   @VariantId(6, variant: LinkedNodeKind.fieldDeclaration)
   LinkedNode get fieldDeclaration_fields;
 
@@ -1914,6 +1929,7 @@
   whileStatement,
   withClause,
   yieldStatement,
+  extensionOverride,
 }
 
 /// Information about a single library in a [LinkedNodeBundle].
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index b3e3783..db8ae22 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -61,6 +61,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.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/error/listener.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
@@ -84,6 +85,7 @@
 import 'package:analyzer/src/summary/prelink.dart';
 import 'package:analyzer/src/summary/resynthesize.dart';
 import 'package:analyzer/src/task/strong_mode.dart';
+import 'package:meta/meta.dart';
 
 final _typesWithImplicitArguments = new Expando();
 
@@ -486,6 +488,11 @@
   @override
   String get name;
 
+  @override
+  InterfaceType get thisType {
+    return type;
+  }
+
   DartType get typeWithDefaultBounds => _typeWithDefaultBounds ??=
       enclosingElement.library._linker.typeSystem.instantiateToBounds(type);
 
@@ -541,6 +548,23 @@
     return null;
   }
 
+  @override
+  InterfaceType instantiate({
+    @required List<DartType> typeArguments,
+    @required NullabilitySuffix nullabilitySuffix,
+  }) {
+    if (typeArguments.length != typeParameters.length) {
+      var ta = 'typeArguments.length (${typeArguments.length})';
+      var tp = 'typeParameters.length (${typeParameters.length})';
+      throw ArgumentError('$ta != $tp');
+    }
+    return InterfaceTypeImpl.explicit(
+      this,
+      typeArguments,
+      nullabilitySuffix: nullabilitySuffix,
+    );
+  }
+
   /// Perform type inference and cycle detection on this class and
   /// store the resulting information in [compilationUnit].
   void link(CompilationUnitElementInBuildUnit compilationUnit);
@@ -5581,10 +5605,16 @@
       _futureDynamicType ??= futureType.instantiate(<DartType>[dynamicType]);
 
   @override
+  ClassElement get futureElement => futureType.element;
+
+  @override
   InterfaceType get futureNullType =>
       _futureNullType ??= futureType.instantiate(<DartType>[nullType]);
 
   @override
+  ClassElement get futureOrElement => futureOrType.element;
+
+  @override
   InterfaceType get futureOrNullType =>
       _futureOrNullType ??= futureOrType.instantiate(<DartType>[nullType]);
 
@@ -5605,6 +5635,9 @@
       iterableType.instantiate(<DartType>[dynamicType]);
 
   @override
+  ClassElement get iterableElement => iterableType.element;
+
+  @override
   InterfaceType get iterableObjectType =>
       _iterableObjectType ??= iterableType.instantiate(<DartType>[objectType]);
 
@@ -5613,10 +5646,16 @@
       _iterableType ??= _buildInterfaceType(_linker.coreLibrary, 'Iterable');
 
   @override
+  ClassElement get listElement => listType.element;
+
+  @override
   InterfaceType get listType =>
       _listType ??= _buildInterfaceType(_linker.coreLibrary, 'List');
 
   @override
+  ClassElement get mapElement => mapType.element;
+
+  @override
   InterfaceType get mapObjectObjectType => _mapObjectObjectType ??=
       mapType.instantiate(<DartType>[objectType, objectType]);
 
@@ -5646,6 +5685,9 @@
       _objectType ??= _buildInterfaceType(_linker.coreLibrary, 'Object');
 
   @override
+  ClassElement get setElement => setType.element;
+
+  @override
   InterfaceType get setType =>
       _setType ??= _buildInterfaceType(_linker.coreLibrary, 'Set');
 
@@ -5658,6 +5700,9 @@
       _streamDynamicType ??= streamType.instantiate(<DartType>[dynamicType]);
 
   @override
+  ClassElement get streamElement => streamType.element;
+
+  @override
   InterfaceType get streamType =>
       _streamType ??= _buildInterfaceType(_linker.asyncLibrary, 'Stream');
 
@@ -5666,6 +5711,9 @@
       _stringType ??= _buildInterfaceType(_linker.coreLibrary, 'String');
 
   @override
+  ClassElement get symbolElement => symbolType.element;
+
+  @override
   InterfaceType get symbolType =>
       _symbolType ??= _buildInterfaceType(_linker.coreLibrary, 'Symbol');
 
@@ -5676,6 +5724,41 @@
   @override
   VoidType get voidType => VoidTypeImpl.instance;
 
+  @override
+  InterfaceType futureOrType2(DartType valueType) {
+    return futureOrType.instantiate([valueType]);
+  }
+
+  @override
+  InterfaceType futureType2(DartType valueType) {
+    return futureType.instantiate([valueType]);
+  }
+
+  @override
+  InterfaceType iterableType2(DartType elementType) {
+    return iterableType.instantiate([elementType]);
+  }
+
+  @override
+  InterfaceType listType2(DartType elementType) {
+    return listType.instantiate([elementType]);
+  }
+
+  @override
+  InterfaceType mapType2(DartType keyType, DartType valueType) {
+    return mapType.instantiate([keyType, valueType]);
+  }
+
+  @override
+  InterfaceType setType2(DartType elementType) {
+    return setType.instantiate([elementType]);
+  }
+
+  @override
+  InterfaceType streamType2(DartType elementType) {
+    return streamType.instantiate([elementType]);
+  }
+
   InterfaceType _buildInterfaceType(
       LibraryElementForLink library, String name) {
     return library.getContainedName(name).buildType((int i) {
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index 4cfe876..0b8c5ac 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -7,6 +7,7 @@
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/handle.dart';
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index fef52b3..a0a089c 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -619,6 +619,24 @@
     }
   }
 
+  ExtensionOverride _read_extensionOverride(LinkedNode data) {
+    var node = astFactory.extensionOverride(
+      extensionName: _readNode(data.extensionOverride_extensionName),
+      argumentList: astFactory.argumentList(
+        _Tokens.OPEN_PAREN,
+        _readNodeList(
+          data.extensionOverride_arguments,
+        ),
+        _Tokens.CLOSE_PAREN,
+      ),
+      typeArguments: _readNode(data.extensionOverride_typeArguments),
+    ) as ExtensionOverrideImpl;
+    node.extendedType = _readType(data.extensionOverride_extendedType);
+    node.typeArgumentTypes =
+        data.extensionOverride_typeArgumentTypes.map(_readType).toList();
+    return node;
+  }
+
   FieldDeclaration _read_fieldDeclaration(LinkedNode data) {
     var node = astFactory.fieldDeclaration2(
       comment: _readDocumentationComment(data),
@@ -1719,6 +1737,8 @@
         return _read_extendsClause(data);
       case LinkedNodeKind.extensionDeclaration:
         return _read_extensionDeclaration(data);
+      case LinkedNodeKind.extensionOverride:
+        return _read_extensionOverride(data);
       case LinkedNodeKind.fieldDeclaration:
         return _read_fieldDeclaration(data);
       case LinkedNodeKind.fieldFormalParameter:
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index 7ee9b12..c85acd5 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -520,6 +520,21 @@
   }
 
   @override
+  LinkedNodeBuilder visitExtensionOverride(ExtensionOverride node) {
+    var builder = LinkedNodeBuilder.extensionOverride(
+      extensionOverride_arguments: _writeNodeList(
+        node.argumentList.arguments,
+      ),
+      extensionOverride_extensionName: node.extensionName.accept(this),
+      extensionOverride_typeArguments: node.typeArguments?.accept(this),
+      extensionOverride_typeArgumentTypes:
+          node.typeArgumentTypes.map(_writeType).toList(),
+      extensionOverride_extendedType: _writeType(node.extendedType),
+    );
+    return builder;
+  }
+
+  @override
   LinkedNodeBuilder visitFieldDeclaration(FieldDeclaration node) {
     var builder = LinkedNodeBuilder.fieldDeclaration(
       fieldDeclaration_fields: node.fields.accept(this),
diff --git a/pkg/analyzer/lib/src/summary2/function_type_builder.dart b/pkg/analyzer/lib/src/summary2/function_type_builder.dart
index 3153f3b..2a00807 100644
--- a/pkg/analyzer/lib/src/summary2/function_type_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/function_type_builder.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/dart/ast/ast.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/ast.dart';
 import 'package:analyzer/src/dart/element/element.dart';
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index 823fef5..6e15f41 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -6,6 +6,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.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/source/line_info.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
diff --git a/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
index 48b3541..6f003ab 100644
--- a/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linking_bundle_context.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/member.dart';
diff --git a/pkg/analyzer/lib/src/summary2/named_type_builder.dart b/pkg/analyzer/lib/src/summary2/named_type_builder.dart
index ff94d7d..1aaa1cc 100644
--- a/pkg/analyzer/lib/src/summary2/named_type_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/named_type_builder.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/dart/ast/ast.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/dart/element/type.dart';
@@ -57,17 +58,11 @@
     var element = this.element;
     if (element is ClassElement) {
       var parameters = element.typeParameters;
-      if (parameters.isEmpty) {
-        var rawType = element.type;
-        _type = (rawType as TypeImpl).withNullability(nullabilitySuffix);
-      } else {
-        var arguments = _buildArguments(parameters);
-        _type = InterfaceTypeImpl.explicit(
-          element,
-          arguments,
-          nullabilitySuffix: nullabilitySuffix,
-        );
-      }
+      var arguments = _buildArguments(parameters);
+      _type = element.instantiate(
+        typeArguments: arguments,
+        nullabilitySuffix: nullabilitySuffix,
+      );
     } else if (element is GenericTypeAliasElement) {
       // Break a possible recursion.
       _type = _dynamicType;
@@ -83,9 +78,12 @@
         _type = substitution.substituteType(rawType);
       }
     } else if (element is NeverElementImpl) {
-      _type = element.type.withNullability(nullabilitySuffix);
+      _type = BottomTypeImpl.instance.withNullability(nullabilitySuffix);
     } else if (element is TypeParameterElement) {
-      _type = TypeParameterTypeImpl(element);
+      _type = TypeParameterTypeImpl(
+        element,
+        nullabilitySuffix: nullabilitySuffix,
+      );
     } else {
       _type = _dynamicType;
     }
@@ -108,7 +106,9 @@
 
   /// Build arguments that correspond to the type [parameters].
   List<DartType> _buildArguments(List<TypeParameterElement> parameters) {
-    if (arguments.isNotEmpty) {
+    if (parameters.isEmpty) {
+      return const <DartType>[];
+    } else if (arguments.isNotEmpty) {
       if (arguments.length == parameters.length) {
         var result = List<DartType>(parameters.length);
         for (int i = 0; i < result.length; ++i) {
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
index 6392ba2..e55e10c 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -6,6 +6,7 @@
 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/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
diff --git a/pkg/analyzer/lib/src/summary2/types_builder.dart b/pkg/analyzer/lib/src/summary2/types_builder.dart
index e7733c3..b60d334 100644
--- a/pkg/analyzer/lib/src/summary2/types_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/types_builder.dart
@@ -342,7 +342,7 @@
   void _infer(ClassElementImpl element, WithClause withClause) {
     element.linkedMixinInferenceCallback = _callbackWhenLoop;
     try {
-      _MixinInference(typeSystem, element.type).perform(withClause);
+      _MixinInference(typeSystem, element.thisType).perform(withClause);
     } finally {
       element.linkedMixinInferenceCallback = null;
     }
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 634baf4..ddf6cf8 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -12,6 +12,7 @@
 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/error/error.dart';
 import 'package:analyzer/error/listener.dart';
@@ -139,6 +140,14 @@
 
   bool get failure => _failure;
 
+  NullabilitySuffix get _noneOrStarSuffix {
+    return _nonNullableEnabled
+        ? NullabilitySuffix.none
+        : NullabilitySuffix.star;
+  }
+
+  bool get _nonNullableEnabled => _featureSet.isEnabled(Feature.non_nullable);
+
   void checkArgument(Expression arg, DartType expectedType) {
     // Preserve named argument structure, so their immediate parent is the
     // method invocation.
@@ -184,13 +193,12 @@
     } else if (element is SpreadElement) {
       // Spread expression may be dynamic in which case it's implicitly downcast
       // to Iterable<dynamic>
-      DartType expressionCastType =
-          typeProvider.iterableType.instantiate([DynamicTypeImpl.instance]);
+      DartType expressionCastType = typeProvider.iterableDynamicType;
       checkAssignment(element.expression, expressionCastType);
 
       var exprType = element.expression.staticType;
       var asIterableType = exprType is InterfaceTypeImpl
-          ? exprType.asInstanceOf(typeProvider.iterableType.element)
+          ? exprType.asInstanceOf(typeProvider.iterableElement)
           : null;
       var elementType =
           asIterableType == null ? null : asIterableType.typeArguments[0];
@@ -223,13 +231,13 @@
     } else if (element is SpreadElement) {
       // Spread expression may be dynamic in which case it's implicitly downcast
       // to Map<dynamic, dynamic>
-      DartType expressionCastType = typeProvider.mapType
-          .instantiate([DynamicTypeImpl.instance, DynamicTypeImpl.instance]);
+      DartType expressionCastType = typeProvider.mapType2(
+          DynamicTypeImpl.instance, DynamicTypeImpl.instance);
       checkAssignment(element.expression, expressionCastType);
 
       var exprType = element.expression.staticType;
       var asMapType = exprType is InterfaceTypeImpl
-          ? exprType.asInstanceOf(typeProvider.mapType.element)
+          ? exprType.asInstanceOf(typeProvider.mapElement)
           : null;
 
       var elementKeyType =
@@ -350,6 +358,7 @@
     node.visitChildren(this);
   }
 
+  // Check invocations
   /// Check constructor declaration to ensure correct super call placement.
   @override
   void visitConstructorDeclaration(ConstructorDeclaration node) {
@@ -373,7 +382,6 @@
     node.visitChildren(this);
   }
 
-  // Check invocations
   @override
   void visitDefaultFormalParameter(DefaultFormalParameter node) {
     // Check that defaults have the proper subtype.
@@ -997,22 +1005,22 @@
 
     var type = functionType.returnType;
 
-    InterfaceType expectedType = null;
+    ClassElement expectedElement = null;
     if (body.isAsynchronous) {
       if (body.isGenerator) {
         // Stream<T> -> T
-        expectedType = typeProvider.streamType;
+        expectedElement = typeProvider.streamElement;
       } else {
         // Future<T> -> FutureOr<T>
-        var typeArg = (type.element == typeProvider.futureType.element)
+        var typeArg = (type.element == typeProvider.futureElement)
             ? (type as InterfaceType).typeArguments[0]
             : typeProvider.dynamicType;
-        return typeProvider.futureOrType.instantiate([typeArg]);
+        return typeProvider.futureOrType2(typeArg);
       }
     } else {
       if (body.isGenerator) {
         // Iterable<T> -> T
-        expectedType = typeProvider.iterableType;
+        expectedElement = typeProvider.iterableElement;
       } else {
         // T -> T
         return type;
@@ -1021,7 +1029,10 @@
     if (yieldStar) {
       if (type.isDynamic) {
         // Ensure it's at least a Stream / Iterable.
-        return expectedType.instantiate([typeProvider.dynamicType]);
+        return expectedElement.instantiate(
+          typeArguments: [typeProvider.dynamicType],
+          nullabilitySuffix: _noneOrStarSuffix,
+        );
       } else {
         // Analyzer will provide a separate error if expected type
         // is not compatible with type.
@@ -1030,7 +1041,7 @@
     }
     if (type.isDynamic) {
       return type;
-    } else if (type is InterfaceType && type.element == expectedType.element) {
+    } else if (type is InterfaceType && type.element == expectedElement) {
       return type.typeArguments[0];
     } else {
       // Malformed type - fallback on analyzer error.
@@ -1128,7 +1139,7 @@
     // In this case, we're more permissive than assignability.
     if (to.isDartAsyncFutureOr) {
       var to1 = (to as InterfaceType).typeArguments[0];
-      var to2 = typeProvider.futureType.instantiate([to1]);
+      var to2 = typeProvider.futureType2(to1);
       return _needsImplicitCast(expr, to1, from: from) == true ||
           _needsImplicitCast(expr, to2, from: from) == true;
     }
@@ -1353,19 +1364,20 @@
           'Unexpected parent of ForEachParts: ${parent.runtimeType}');
     }
     // Find the element type of the sequence.
-    var sequenceInterface = awaitKeyword != null
-        ? typeProvider.streamType
-        : typeProvider.iterableType;
+    var sequenceElement = awaitKeyword != null
+        ? typeProvider.streamElement
+        : typeProvider.iterableElement;
     var iterableType = _getExpressionType(node.iterable);
-    var elementType =
-        _getInstanceTypeArgument(iterableType, sequenceInterface.element);
+    var elementType = _getInstanceTypeArgument(iterableType, sequenceElement);
 
     // If the sequence is not an Iterable (or Stream for await for) but is a
     // supertype of it, do an implicit downcast to Iterable<dynamic>. Then
     // we'll do a separate cast of the dynamic element to the variable's type.
     if (elementType == null) {
-      var sequenceType =
-          sequenceInterface.instantiate([DynamicTypeImpl.instance]);
+      var sequenceType = sequenceElement.instantiate(
+        typeArguments: [typeProvider.dynamicType],
+        nullabilitySuffix: _noneOrStarSuffix,
+      );
 
       if (rules.isSubtypeOf(sequenceType, iterableType)) {
         _recordImplicitCast(node.iterable, sequenceType, from: iterableType);
@@ -1393,7 +1405,7 @@
 
   void check(Declaration node) {
     var element = node.declaredElement as ClassElement;
-    if (element.type.isObject) {
+    if (element.isDartCoreObject) {
       return;
     }
     _checkForCovariantGenerics(node, element);
diff --git a/pkg/analyzer/lib/src/task/strong_mode.dart b/pkg/analyzer/lib/src/task/strong_mode.dart
index 7b86364c..21fcc0a 100644
--- a/pkg/analyzer/lib/src/task/strong_mode.dart
+++ b/pkg/analyzer/lib/src/task/strong_mode.dart
@@ -307,7 +307,7 @@
         //
         // Then infer the types for the members.
         //
-        this.interfaceType = classElement.type;
+        this.interfaceType = classElement.thisType;
         for (FieldElement field in classElement.fields) {
           _inferField(field);
         }
diff --git a/pkg/analyzer/lib/src/test_utilities/find_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
index e02ea7e..acef919 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -127,6 +127,10 @@
     return _node(search, (n) => n is FunctionTypeAlias);
   }
 
+  FunctionTypedFormalParameter functionTypedFormalParameter(String search) {
+    return _node(search, (n) => n is FunctionTypedFormalParameter);
+  }
+
   GenericFunctionType genericFunctionType(String search) {
     return _node(search, (n) => n is GenericFunctionType);
   }
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 382edb0..176212d 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -346,6 +346,7 @@
   void addAll(Iterable<E> iterable) {}
   void clear() {}
   int indexOf(Object element);
+  E removeLast() {}
 
   noSuchMethod(Invocation invocation) => null;
 }
@@ -393,6 +394,7 @@
   int operator ~/(num other);
 
   num abs();
+  int floor();
   int round();
   double toDouble();
   int toInt();
@@ -498,7 +500,147 @@
       '$sdkRoot/lib/html/dart2js/html_dart2js.dart',
       '''
 library dart.html;
-class HtmlElement {}
+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 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 OptionElement extends HtmlElement {
+  factory OptionElement({String data: '', String value : '', bool selected: false}) {
+  }
+
+  factory OptionElement._([String data, String value, bool defaultSelected, bool selected]) {
+  }
+}
+
+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) {}
 ''',
     )
   ],
@@ -510,34 +652,148 @@
       'dart:html',
       '$sdkRoot/lib/html/dartium/html_dartium.dart',
       '''
-library dart.dom.html;
+library dart.html;
+import 'dart:async';
 
-final HtmlDocument document;
+class Event {}
+class MouseEvent extends Event {}
+class FocusEvent extends Event {}
+class KeyEvent extends Event {}
 
-abstract class Element {}
+abstract class ElementStream<T extends Event> implements Stream<T> {}
 
-abstract class HtmlDocument {
-  Element query(String relativeSelectors) => null;
+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;
 }
 
-abstract class HtmlElement extends Element {}
+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;
 
-abstract class AnchorElement extends HtmlElement {}
-abstract class BodyElement extends HtmlElement {}
-abstract class ButtonElement extends HtmlElement {}
-abstract class DivElement extends HtmlElement {}
-abstract class InputElement extends HtmlElement {}
-abstract class SelectElement extends HtmlElement {}
+  bool get hidden => null;
+  set hidden(bool value) => null;
 
+  void set className(String s){}
+  void set readOnly(bool b){}
+  void set tabIndex(int i){}
 
-abstract class CanvasElement extends HtmlElement {
-  Object getContext(String contextId, [Map attributes]);
-  CanvasRenderingContext2D get context2D;
+  String _innerHtml;
+  String get innerHtml {
+    throw 'not the real implementation';
+  }
+  set innerHtml(String value) {
+    // stuff
+  }
 }
 
-abstract class CanvasRenderingContext2D {}
+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;
+  }
 
-Element query(String relativeSelectors) => null;
+  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 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 OptionElement extends HtmlElement {
+  factory OptionElement({String data: '', String value : '', bool selected: false}) {
+  }
+
+  factory OptionElement._([String data, String value, bool defaultSelected, bool selected]) {
+  }
+}
+
+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) {}
 ''',
     )
   ],
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 856b19b..85d5856 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk_elements.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk_elements.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';
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 5314552..67ae027 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.38.2
+version: 0.38.3
 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
@@ -13,10 +13,10 @@
   collection: ^1.10.1
   convert: ^2.0.0
   crypto: '>=1.1.1 <3.0.0'
-  front_end: 0.1.24
+  front_end: 0.1.25
   glob: ^1.0.3
   html: '>=0.13.4+1 <0.15.0'
-  kernel: 0.3.24
+  kernel: 0.3.25
   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/cancelable_future_test.dart b/pkg/analyzer/test/cancelable_future_test.dart
deleted file mode 100644
index 4f840aa..0000000
--- a/pkg/analyzer/test/cancelable_future_test.dart
+++ /dev/null
@@ -1,425 +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:async';
-
-import 'package:analyzer/src/cancelable_future.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-void main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(CancelableCompleterTests);
-    defineReflectiveTests(CancelableFutureTests);
-  });
-}
-
-@reflectiveTest
-class CancelableCompleterTests {
-  CancelableCompleter<Object> completer;
-  int cancelCount = 0;
-
-  void setUp() {
-    completer = new CancelableCompleter<Object>(() {
-      cancelCount++;
-    });
-  }
-
-  Future test_cancel_after_cancel() {
-    // It is permissible to cancel multiple times, but only the first
-    // cancellation has any effect.
-    expect(cancelCount, 0);
-    completer.future.cancel();
-    expect(cancelCount, 1);
-    completer.future.cancel();
-    expect(cancelCount, 1);
-    // Make sure the future still completes with error.
-    return completer.future
-        .then((_) {
-          fail('Expected error completion');
-        }, onError: (error) {
-          expect(error, new TypeMatcher<FutureCanceledError>());
-          // And make sure nothing else happens.
-        })
-        .then((_) => pumpEventQueue())
-        .then((_) {
-          expect(completer.isCompleted, isFalse);
-          expect(cancelCount, 1);
-        });
-  }
-
-  Future test_cancel_after_chaining() {
-    bool callbackInvoked = false;
-    completer.future.then((_) {
-      fail('Expected error completion');
-    }, onError: (error) {
-      expect(callbackInvoked, isFalse);
-      expect(error, new TypeMatcher<FutureCanceledError>());
-      callbackInvoked = true;
-    });
-    expect(cancelCount, 0);
-    completer.future.cancel();
-    // The cancel callback should have been invoked immediately.
-    expect(cancelCount, 1);
-    // But the completer should remain in the "not completed" state.
-    expect(completer.isCompleted, isFalse);
-    // The callback should be deferred to a microtask.
-    expect(callbackInvoked, isFalse);
-    return pumpEventQueue().then((_) {
-      expect(callbackInvoked, isTrue);
-      expect(completer.isCompleted, isFalse);
-      expect(cancelCount, 1);
-    });
-  }
-
-  Future test_cancel_after_complete() {
-    Object obj = new Object();
-    completer.complete(obj);
-    completer.future.cancel();
-    // The cancel callback should not have been invoked, because it was too
-    // late to cancel.
-    expect(cancelCount, 0);
-    // Make sure the future still completes with the object.
-    return completer.future
-        .then((result) {
-          expect(result, same(obj));
-          // And make sure nothing else happens.
-        })
-        .then((_) => pumpEventQueue())
-        .then((_) {
-          expect(completer.isCompleted, isTrue);
-          expect(cancelCount, 0);
-        });
-  }
-
-  Future test_cancel_before_chaining() {
-    completer.future.cancel();
-    // The cancel callback should have been invoked immediately.
-    expect(cancelCount, 1);
-    // But the completer should remain in the "not completed" state.
-    expect(completer.isCompleted, isFalse);
-    bool callbackInvoked = false;
-    completer.future.then((_) {
-      fail('Expected error completion');
-    }, onError: (error) {
-      expect(callbackInvoked, isFalse);
-      expect(error, new TypeMatcher<FutureCanceledError>());
-      callbackInvoked = true;
-    });
-    // The callback should be deferred to a microtask.
-    expect(callbackInvoked, isFalse);
-    expect(completer.isCompleted, isFalse);
-    return pumpEventQueue().then((_) {
-      expect(callbackInvoked, isTrue);
-      expect(completer.isCompleted, isFalse);
-      expect(cancelCount, 1);
-    });
-  }
-
-  Future test_complete_after_cancel() {
-    completer.future.cancel();
-    // The cancel callback should have been invoked immediately.
-    expect(cancelCount, 1);
-    // Completing should have no effect other than to set the isCompleted
-    // flag.
-    expect(completer.isCompleted, isFalse);
-    Object obj = new Object();
-    completer.complete(obj);
-    expect(completer.isCompleted, isTrue);
-    // Make sure the future still completer with error.
-    return completer.future
-        .then((_) {
-          fail('Expected error completion');
-        }, onError: (error) {
-          expect(error, new TypeMatcher<FutureCanceledError>());
-          // And make sure nothing else happens.
-        })
-        .then((_) => pumpEventQueue())
-        .then((_) {
-          expect(completer.isCompleted, isTrue);
-          expect(cancelCount, 1);
-        });
-  }
-
-  Future test_complete_after_chaining() {
-    Object obj = new Object();
-    bool callbackInvoked = false;
-    completer.future.then((result) {
-      expect(callbackInvoked, isFalse);
-      expect(result, same(obj));
-      callbackInvoked = true;
-    }, onError: (error) {
-      fail('Expected successful completion');
-    });
-    expect(completer.isCompleted, isFalse);
-    // Running the event loop should have no effect since the completer hasn't
-    // been completed yet.
-    return pumpEventQueue()
-        .then((_) {
-          completer.complete(obj);
-          expect(completer.isCompleted, isTrue);
-          // The callback should be deferred to a microtask.
-          expect(callbackInvoked, isFalse);
-        })
-        .then((_) => pumpEventQueue())
-        .then((_) {
-          expect(callbackInvoked, isTrue);
-          expect(completer.isCompleted, isTrue);
-          expect(cancelCount, 0);
-        });
-  }
-
-  void test_complete_after_complete() {
-    // As with an ordinary Completer, calling complete() (or completeError)
-    // after calling complete() should throw an exception.
-    completer.complete();
-    expect(() {
-      completer.complete();
-    }, throwsStateError);
-    expect(() {
-      completer.completeError(new Object());
-    }, throwsStateError);
-  }
-
-  void test_complete_after_completeError() {
-    // As with an ordinary Completer, calling complete() (or completeError)
-    // after calling completeError() should throw an exception.
-    completer.completeError(new Object());
-    expect(() {
-      completer.complete();
-    }, throwsStateError);
-    expect(() {
-      completer.completeError(new Object());
-    }, throwsStateError);
-    // Now absorb the error that's in the completer's future.
-    completer.future.catchError((_) => null);
-  }
-
-  Future test_complete_before_chaining() {
-    Object obj = new Object();
-    completer.complete(obj);
-    expect(completer.isCompleted, isTrue);
-    bool callbackInvoked = false;
-    completer.future.then((result) {
-      expect(callbackInvoked, isFalse);
-      expect(result, same(obj));
-      callbackInvoked = true;
-    }, onError: (error) {
-      fail('Expected successful completion');
-    });
-    // The callback should be deferred to a microtask.
-    expect(callbackInvoked, isFalse);
-    expect(completer.isCompleted, isTrue);
-    return pumpEventQueue().then((_) {
-      expect(callbackInvoked, isTrue);
-      expect(completer.isCompleted, isTrue);
-      expect(cancelCount, 0);
-    });
-  }
-
-  Future test_completeError_after_cancel() {
-    completer.future.cancel();
-    // The cancel callback should have been invoked immediately.
-    expect(cancelCount, 1);
-    // Completing should have no effect other than to set the isCompleted
-    // flag.
-    expect(completer.isCompleted, isFalse);
-    Object obj = new Object();
-    completer.completeError(obj);
-    expect(completer.isCompleted, isTrue);
-    // Make sure the future still completes with error.
-    return completer.future
-        .then((_) {
-          fail('Expected error completion');
-        }, onError: (error) {
-          expect(error, new TypeMatcher<FutureCanceledError>());
-          // And make sure nothing else happens.
-        })
-        .then((_) => pumpEventQueue())
-        .then((_) {
-          expect(completer.isCompleted, isTrue);
-          expect(cancelCount, 1);
-        });
-  }
-
-  Future test_completeError_after_chaining() {
-    Object obj = new Object();
-    bool callbackInvoked = false;
-    completer.future.then((_) {
-      fail('Expected error completion');
-    }, onError: (error) {
-      expect(callbackInvoked, isFalse);
-      expect(error, same(obj));
-      callbackInvoked = true;
-    });
-    expect(completer.isCompleted, isFalse);
-    // Running the event loop should have no effect since the completer hasn't
-    // been completed yet.
-    return pumpEventQueue()
-        .then((_) {
-          completer.completeError(obj);
-          expect(completer.isCompleted, isTrue);
-          // The callback should be deferred to a microtask.
-          expect(callbackInvoked, isFalse);
-        })
-        .then((_) => pumpEventQueue())
-        .then((_) {
-          expect(callbackInvoked, isTrue);
-          expect(completer.isCompleted, isTrue);
-          expect(cancelCount, 0);
-        });
-  }
-
-  Future test_completeError_before_chaining() {
-    Object obj = new Object();
-    completer.completeError(obj);
-    expect(completer.isCompleted, isTrue);
-    bool callbackInvoked = false;
-    completer.future.then((_) {
-      fail('Expected error completion');
-    }, onError: (error) {
-      expect(callbackInvoked, isFalse);
-      expect(error, same(obj));
-      callbackInvoked = true;
-    });
-    // The callback should be deferred to a microtask.
-    expect(callbackInvoked, isFalse);
-    expect(completer.isCompleted, isTrue);
-    return pumpEventQueue().then((_) {
-      expect(callbackInvoked, isTrue);
-      expect(completer.isCompleted, isTrue);
-      expect(cancelCount, 0);
-    });
-  }
-
-  void test_initialState() {
-    expect(completer.isCompleted, isFalse);
-    expect(cancelCount, 0);
-  }
-}
-
-@reflectiveTest
-class CancelableFutureTests {
-  Future test_defaultConstructor_returnFuture() {
-    Object obj = new Object();
-    bool callbackInvoked = false;
-    new CancelableFuture(() => new Future(() => obj)).then((result) {
-      expect(callbackInvoked, isFalse);
-      expect(result, same(obj));
-      callbackInvoked = true;
-    }, onError: (error) {
-      fail('Expected successful completion');
-    });
-    expect(callbackInvoked, isFalse);
-    return pumpEventQueue().then((_) {
-      expect(callbackInvoked, isTrue);
-    });
-  }
-
-  Future test_defaultConstructor_returnValue() {
-    Object obj = new Object();
-    bool callbackInvoked = false;
-    new CancelableFuture(() => obj).then((result) {
-      expect(callbackInvoked, isFalse);
-      expect(result, same(obj));
-      callbackInvoked = true;
-    }, onError: (error) {
-      fail('Expected successful completion');
-    });
-    expect(callbackInvoked, isFalse);
-    return pumpEventQueue().then((_) {
-      expect(callbackInvoked, isTrue);
-    });
-  }
-
-  Future test_defaultConstructor_throwException() {
-    Object obj = new Object();
-    bool callbackInvoked = false;
-    new CancelableFuture(() {
-      throw obj;
-    }).then((result) {
-      fail('Expected error completion');
-    }, onError: (error) {
-      expect(callbackInvoked, isFalse);
-      expect(error, same(obj));
-      callbackInvoked = true;
-    });
-    expect(callbackInvoked, isFalse);
-    return pumpEventQueue().then((_) {
-      expect(callbackInvoked, isTrue);
-    });
-  }
-
-  Future test_delayed_noCallback() {
-    DateTime start = new DateTime.now();
-    return new CancelableFuture.delayed(new Duration(seconds: 1))
-        .then((result) {
-      DateTime end = new DateTime.now();
-      expect(result, isNull);
-      expect(end.difference(start).inMilliseconds > 900, isTrue);
-    });
-  }
-
-  Future test_delayed_withCallback() {
-    Object obj = new Object();
-    DateTime start = new DateTime.now();
-    return new CancelableFuture.delayed(new Duration(seconds: 1), () {
-      DateTime end = new DateTime.now();
-      expect(end.difference(start).inMilliseconds > 900, isTrue);
-      return obj;
-    }).then((result) {
-      expect(result, same(obj));
-    });
-  }
-
-  Future test_error() {
-    Object obj = new Object();
-    return new CancelableFuture.error(obj).then((result) {
-      fail('Expected error completion');
-    }, onError: (error) {
-      expect(error, same(obj));
-    });
-  }
-
-  Future test_microtask() {
-    Object obj = new Object();
-    bool callbackInvoked = false;
-    new CancelableFuture.microtask(() => obj).then((result) {
-      expect(callbackInvoked, isFalse);
-      expect(result, same(obj));
-      callbackInvoked = true;
-    }, onError: (error) {
-      fail('Expected successful completion');
-    });
-    expect(callbackInvoked, isFalse);
-    return pumpEventQueue().then((_) {
-      expect(callbackInvoked, isTrue);
-    });
-  }
-
-  Future test_sync() {
-    Object obj = new Object();
-    bool callbackInvoked = false;
-    new CancelableFuture.sync(() => obj).then((result) {
-      expect(callbackInvoked, isFalse);
-      expect(result, same(obj));
-      callbackInvoked = true;
-    }, onError: (error) {
-      fail('Expected successful completion');
-    });
-    expect(callbackInvoked, isFalse);
-    return pumpEventQueue().then((_) {
-      expect(callbackInvoked, isTrue);
-    });
-  }
-
-  Future test_value() {
-    Object obj = new Object();
-    return new CancelableFuture.value(obj).then((result) {
-      expect(result, same(obj));
-    }, onError: (error) {
-      fail('Expected successful completion');
-    });
-  }
-}
diff --git a/pkg/analyzer/test/dart/ast/ast_test.dart b/pkg/analyzer/test/dart/ast/ast_test.dart
index 9c90698..163cb6c 100644
--- a/pkg/analyzer/test/dart/ast/ast_test.dart
+++ b/pkg/analyzer/test/dart/ast/ast_test.dart
@@ -26,8 +26,10 @@
     defineReflectiveTests(FieldFormalParameterTest);
     defineReflectiveTests(IndexExpressionTest);
     defineReflectiveTests(MethodDeclarationTest);
+    defineReflectiveTests(MethodInvocationTest);
     defineReflectiveTests(NodeListTest);
     defineReflectiveTests(PreviousTokenTest);
+    defineReflectiveTests(PropertyAccessTest);
     defineReflectiveTests(SimpleIdentifierTest);
     defineReflectiveTests(SimpleStringLiteralTest);
     defineReflectiveTests(SpreadElementTest);
@@ -322,6 +324,22 @@
     AstTestFactory.prefixExpression(TokenType.PLUS_PLUS, expression);
     expect(expression.inSetterContext(), isTrue);
   }
+
+  void test_isNullAware_regularIndex() {
+    final expression = AstTestFactory.indexExpression(
+        AstTestFactory.nullLiteral(),
+        AstTestFactory.nullLiteral(),
+        TokenType.OPEN_SQUARE_BRACKET);
+    expect(expression.isNullAware, isFalse);
+  }
+
+  void test_isNullAware_true() {
+    final expression = AstTestFactory.indexExpression(
+        AstTestFactory.nullLiteral(),
+        AstTestFactory.nullLiteral(),
+        TokenType.QUESTION_PERIOD_OPEN_SQUARE_BRACKET);
+    expect(expression.isNullAware, isTrue);
+  }
 }
 
 @reflectiveTest
@@ -363,6 +381,31 @@
 }
 
 @reflectiveTest
+class MethodInvocationTest extends ParserTestCase {
+  void test_isNullAware_cascade() {
+    final invocation = AstTestFactory.methodInvocation3(
+        AstTestFactory.nullLiteral(), 'foo', null, [], TokenType.PERIOD_PERIOD);
+    expect(invocation.isNullAware, isFalse);
+  }
+
+  void test_isNullAware_regularInvocation() {
+    final invocation = AstTestFactory.methodInvocation3(
+        AstTestFactory.nullLiteral(), 'foo', null, [], TokenType.PERIOD);
+    expect(invocation.isNullAware, isFalse);
+  }
+
+  void test_isNullAware_true() {
+    final invocation = AstTestFactory.methodInvocation3(
+        AstTestFactory.nullLiteral(),
+        'foo',
+        null,
+        [],
+        TokenType.QUESTION_PERIOD);
+    expect(invocation.isNullAware, isTrue);
+  }
+}
+
+@reflectiveTest
 class NodeListTest extends EngineTestCase {
   void test_add() {
     AstNode parent = AstTestFactory.argumentList();
@@ -712,6 +755,27 @@
 }
 
 @reflectiveTest
+class PropertyAccessTest extends ParserTestCase {
+  void test_isNullAware_cascade() {
+    final invocation = AstTestFactory.propertyAccess2(
+        AstTestFactory.nullLiteral(), 'foo', TokenType.PERIOD_PERIOD);
+    expect(invocation.isNullAware, isFalse);
+  }
+
+  void test_isNullAware_regularPropertyAccess() {
+    final invocation = AstTestFactory.propertyAccess2(
+        AstTestFactory.nullLiteral(), 'foo', TokenType.PERIOD);
+    expect(invocation.isNullAware, isFalse);
+  }
+
+  void test_isNullAware_true() {
+    final invocation = AstTestFactory.propertyAccess2(
+        AstTestFactory.nullLiteral(), 'foo', TokenType.QUESTION_PERIOD);
+    expect(invocation.isNullAware, isTrue);
+  }
+}
+
+@reflectiveTest
 class SimpleIdentifierTest extends ParserTestCase {
   void test_inGetterContext() {
     for (_WrapperKind wrapper in _WrapperKind.values) {
diff --git a/pkg/analyzer/test/dart/element/builder_test.dart b/pkg/analyzer/test/dart/element/builder_test.dart
index adfcf2e..92d475a 100644
--- a/pkg/analyzer/test/dart/element/builder_test.dart
+++ b/pkg/analyzer/test/dart/element/builder_test.dart
@@ -6,6 +6,7 @@
 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';
@@ -2540,7 +2541,13 @@
     expect(alias, isNotNull);
     assertHasCodeRange(alias, 50, 31);
     expect(alias.name, aliasName);
-    expect(alias.type, isNotNull);
+    expect(
+      alias.instantiate2(
+        typeArguments: [],
+        nullabilitySuffix: NullabilitySuffix.none,
+      ),
+      isNotNull,
+    );
     expect(alias.isSynthetic, isFalse);
     List<VariableElement> parameters = alias.parameters;
     expect(parameters, hasLength(2));
@@ -2567,7 +2574,6 @@
     GenericTypeAliasElementImpl alias = aliases[0];
     expect(alias, isNotNull);
     expect(alias.name, aliasName);
-    expect(alias.type, isNotNull);
     expect(alias.isSynthetic, isFalse);
     List<VariableElement> parameters = alias.parameters;
     expect(parameters, isNotNull);
diff --git a/pkg/analyzer/test/error/error_reporter_test.dart b/pkg/analyzer/test/error/error_reporter_test.dart
index eeb2468..a796291 100644
--- a/pkg/analyzer/test/error/error_reporter_test.dart
+++ b/pkg/analyzer/test/error/error_reporter_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:source_span/source_span.dart';
@@ -106,8 +107,14 @@
     var aImport = findElement.importFind('package:test/a.dart');
     var bImport = findElement.importFind('package:test/b.dart');
 
-    var firstType = aImport.class_('A').type;
-    var secondType = bImport.class_('B').type;
+    var firstType = aImport.class_('A').instantiate(
+      typeArguments: [],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+    var secondType = bImport.class_('B').instantiate(
+      typeArguments: [],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
 
     var reporter = ErrorReporter(listener, firstType.element.source);
 
@@ -137,8 +144,14 @@
     var aImport = findElement.importFind('package:test/a.dart');
     var bImport = findElement.importFind('package:test/b.dart');
 
-    var firstType = aImport.class_('A').type;
-    var secondType = bImport.class_('A').type;
+    var firstType = aImport.class_('A').instantiate(
+      typeArguments: [],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+    var secondType = bImport.class_('A').instantiate(
+      typeArguments: [],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
 
     var reporter = ErrorReporter(listener, firstType.element.source);
     reporter.reportTypeErrorForNode(
diff --git a/pkg/analyzer/test/file_system/memory_file_system_test.dart b/pkg/analyzer/test/file_system/memory_file_system_test.dart
index 443e842..76ee1651 100644
--- a/pkg/analyzer/test/file_system/memory_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/memory_file_system_test.dart
@@ -114,10 +114,6 @@
     expect(contents.data, defaultFileContent);
   }
 
-  test_encoding() {
-    expect(source.encoding, new Uri.file(defaultFilePath).toString());
-  }
-
   test_equals_false_differentFile() {
     File fileA = getFile(exists: false, filePath: join(tempPath, 'a.dart'));
     File fileB = getFile(exists: false, filePath: join(tempPath, 'b.dart'));
@@ -196,10 +192,6 @@
     expect(() => source.contents, throwsA(isFileSystemException));
   }
 
-  test_encoding() {
-    expect(source.encoding, new Uri.file(defaultFilePath).toString());
-  }
-
   test_exists() {
     expect(source.exists(), isFalse);
   }
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index 7e37544..a0153b8 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -2,24 +2,15 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/src/dart/element/builder.dart';
-import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart' hide SdkLibrariesReader;
-import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/java_engine_io.dart';
 import 'package:analyzer/src/generated/java_io.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/source_io.dart';
-import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
-import 'package:analyzer/src/generated/testing/test_type_provider.dart';
-import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:test/test.dart';
@@ -33,7 +24,6 @@
     // ignore: deprecated_member_use_from_same_package
     defineReflectiveTests(CustomUriResolverTest);
     defineReflectiveTests(DartUriResolverTest);
-    defineReflectiveTests(EnumMemberBuilderTest);
     defineReflectiveTests(ErrorSeverityTest);
     defineReflectiveTests(FileBasedSourceTest);
     defineReflectiveTests(ResolveRelativeUriTest);
@@ -144,100 +134,6 @@
 }
 
 @reflectiveTest
-class EnumMemberBuilderTest extends EngineTestCase {
-  test_visitEnumDeclaration_multiple() async {
-    String firstName = "ONE";
-    String secondName = "TWO";
-    String thirdName = "THREE";
-    EnumDeclaration enumDeclaration = AstTestFactory.enumDeclaration2(
-        "E", [firstName, secondName, thirdName]);
-
-    ClassElement enumElement = _buildElement(enumDeclaration);
-    List<FieldElement> fields = enumElement.fields;
-    expect(fields, hasLength(5));
-
-    FieldElement constant = fields[2];
-    expect(constant, isNotNull);
-    expect(constant.name, firstName);
-    expect(constant.isStatic, isTrue);
-    expect((constant as FieldElementImpl).evaluationResult, isNotNull);
-    _assertGetter(constant);
-
-    constant = fields[3];
-    expect(constant, isNotNull);
-    expect(constant.name, secondName);
-    expect(constant.isStatic, isTrue);
-    expect((constant as FieldElementImpl).evaluationResult, isNotNull);
-    _assertGetter(constant);
-
-    constant = fields[4];
-    expect(constant, isNotNull);
-    expect(constant.name, thirdName);
-    expect(constant.isStatic, isTrue);
-    expect((constant as FieldElementImpl).evaluationResult, isNotNull);
-    _assertGetter(constant);
-  }
-
-  test_visitEnumDeclaration_single() async {
-    String firstName = "ONE";
-    EnumDeclaration enumDeclaration =
-        AstTestFactory.enumDeclaration2("E", [firstName]);
-    enumDeclaration.constants[0].documentationComment =
-        AstTestFactory.documentationComment(
-            [TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
-
-    ClassElement enumElement = _buildElement(enumDeclaration);
-    List<FieldElement> fields = enumElement.fields;
-    expect(fields, hasLength(3));
-
-    FieldElement field = fields[0];
-    expect(field, isNotNull);
-    expect(field.name, "index");
-    expect(field.isStatic, isFalse);
-    expect(field.isSynthetic, isTrue);
-    _assertGetter(field);
-
-    field = fields[1];
-    expect(field, isNotNull);
-    expect(field.name, "values");
-    expect(field.isStatic, isTrue);
-    expect(field.isSynthetic, isTrue);
-    expect((field as FieldElementImpl).evaluationResult, isNotNull);
-    _assertGetter(field);
-
-    FieldElement constant = fields[2];
-    expect(constant, isNotNull);
-    expect(constant.name, firstName);
-    expect(constant.isStatic, isTrue);
-    expect((constant as FieldElementImpl).evaluationResult, isNotNull);
-    expect(constant.documentationComment, '/// aaa');
-    _assertGetter(constant);
-  }
-
-  void _assertGetter(FieldElement field) {
-    PropertyAccessorElement getter = field.getter;
-    expect(getter, isNotNull);
-    expect(getter.variable, same(field));
-    expect(getter.type, isNotNull);
-  }
-
-  ClassElement _buildElement(EnumDeclaration enumDeclaration) {
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder elementBuilder = _makeBuilder(holder);
-    enumDeclaration.accept(elementBuilder);
-    EnumMemberBuilder memberBuilder =
-        new EnumMemberBuilder(new TestTypeProvider());
-    enumDeclaration.accept(memberBuilder);
-    List<ClassElement> enums = holder.enums;
-    expect(enums, hasLength(1));
-    return enums[0];
-  }
-
-  ElementBuilder _makeBuilder(ElementHolder holder) =>
-      new ElementBuilder(holder, new CompilationUnitElementImpl());
-}
-
-@reflectiveTest
 class ErrorSeverityTest extends EngineTestCase {
   test_max_error_error() async {
     expect(ErrorSeverity.ERROR.max(ErrorSeverity.ERROR),
@@ -351,15 +247,6 @@
     FileBasedSource.fileReadMode = (String s) => s;
   }
 
-  test_getEncoding() async {
-    SourceFactory factory = new SourceFactory(
-        [new ResourceUriResolver(PhysicalResourceProvider.INSTANCE)]);
-    String fullPath = "/does/not/exist.dart";
-    JavaFile file = FileUtilities2.createFile(fullPath);
-    FileBasedSource source = new FileBasedSource(file);
-    expect(factory.fromEncoding(source.encoding), source);
-  }
-
   test_getFullName() async {
     String fullPath = "/does/not/exist.dart";
     JavaFile file = FileUtilities2.createFile(fullPath);
diff --git a/pkg/analyzer/test/generated/compile_time_error_code.dart b/pkg/analyzer/test/generated/compile_time_error_code.dart
index f4aad69..49b349f 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code.dart
@@ -32,6 +32,7 @@
     ]);
   }
 
+  @failingTest
   test_accessPrivateEnumField() async {
     await assertErrorsInCode(r'''
 enum E { ONE }
@@ -375,8 +376,6 @@
   }
 
   test_constConstructorWithFieldInitializedByNonConst() async {
-    // TODO(paulberry): the error CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE is
-    // redundant and ought to be suppressed.
     await assertErrorsInCode(r'''
 class A {
   final int i = f();
@@ -386,8 +385,6 @@
   return 3;
 }
 ''', [
-      error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 26,
-          3),
       error(
           CompileTimeErrorCode
               .CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST,
diff --git a/pkg/analyzer/test/generated/element_resolver_test.dart b/pkg/analyzer/test/generated/element_resolver_test.dart
index f74fe27..a03c601 100644
--- a/pkg/analyzer/test/generated/element_resolver_test.dart
+++ b/pkg/analyzer/test/generated/element_resolver_test.dart
@@ -26,6 +26,7 @@
 
 import '../src/dart/resolution/driver_resolution.dart';
 import '../util/element_type_matchers.dart';
+import 'elements_types_mixin.dart';
 import 'test_analysis_context.dart';
 import 'test_support.dart';
 
@@ -297,7 +298,8 @@
 }
 
 @reflectiveTest
-class ElementResolverTest extends EngineTestCase with ResourceProviderMixin {
+class ElementResolverTest extends EngineTestCase
+    with ResourceProviderMixin, ElementsTypesMixin {
   /**
    * The error listener to which errors will be reported.
    */
@@ -323,6 +325,8 @@
    */
   ElementResolver _resolver;
 
+  TypeProvider get typeProvider => _typeProvider;
+
   void fail_visitExportDirective_combinators() {
     _fail("Not yet tested");
     // Need to set up the exported library so that the identifier can be
@@ -392,22 +396,23 @@
     // class B implements A {}
     //
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.interfaces = <InterfaceType>[classA.type];
+    classB.interfaces = <InterfaceType>[interfaceType(classA)];
     //
     // class C extends Object with B {}
     //
     ClassElementImpl classC = ElementFactory.classElement2("C");
-    classC.mixins = <InterfaceType>[classB.type];
+    classC.mixins = <InterfaceType>[interfaceType(classB)];
     //
     // class D extends C {}
     //
-    ClassElementImpl classD = ElementFactory.classElement("D", classC.type);
+    ClassElementImpl classD =
+        ElementFactory.classElement("D", interfaceType(classC));
     //
     // D a;
     // a[i];
     //
     SimpleIdentifier array = AstTestFactory.identifier3("a");
-    array.staticType = classD.type;
+    array.staticType = interfaceType(classD);
     IndexExpression expression =
         AstTestFactory.indexExpression(array, AstTestFactory.identifier3("i"));
     expect(_resolveIndexExpression(expression), same(operator));
@@ -852,9 +857,9 @@
     classA.accessors = <PropertyAccessorElement>[getter];
     SimpleIdentifier target = AstTestFactory.identifier3("a");
     VariableElementImpl variable = ElementFactory.localVariableElement(target);
-    variable.type = classA.type;
+    variable.type = interfaceType(classA);
     target.staticElement = variable;
-    target.staticType = classA.type;
+    target.staticType = interfaceType(classA);
     PrefixedIdentifier identifier = AstTestFactory.identifier(
         target, AstTestFactory.identifier3(getterName));
     _resolveNode(identifier);
@@ -868,14 +873,14 @@
     // set accessors
     String propName = "b";
     PropertyAccessorElement getter =
-        ElementFactory.getterElement(propName, false, _typeProvider.intType);
+        ElementFactory.getterElement(propName, true, _typeProvider.intType);
     PropertyAccessorElement setter =
-        ElementFactory.setterElement(propName, false, _typeProvider.intType);
+        ElementFactory.setterElement(propName, true, _typeProvider.intType);
     classA.accessors = <PropertyAccessorElement>[getter, setter];
-    // prepare "A.m"
+    // prepare "A.b"
     SimpleIdentifier target = AstTestFactory.identifier3("A");
     target.staticElement = classA;
-    target.staticType = classA.type;
+    target.staticType = interfaceType(classA);
     PrefixedIdentifier identifier =
         AstTestFactory.identifier(target, AstTestFactory.identifier3(propName));
     // resolve
@@ -889,17 +894,16 @@
     ClassElementImpl classA = ElementFactory.classElement2("A");
     // set methods
     String propName = "m";
-    MethodElement method =
-        ElementFactory.methodElement("m", _typeProvider.intType);
+    var method = ElementFactory.methodElement("m", _typeProvider.intType);
+    method.isStatic = true;
     classA.methods = <MethodElement>[method];
     // prepare "A.m"
     SimpleIdentifier target = AstTestFactory.identifier3("A");
     target.staticElement = classA;
-    target.staticType = classA.type;
+    target.staticType = interfaceType(classA);
     PrefixedIdentifier identifier =
         AstTestFactory.identifier(target, AstTestFactory.identifier3(propName));
-    AstTestFactory.assignmentExpression(
-        identifier, TokenType.EQ, AstTestFactory.nullLiteral());
+    AstTestFactory.expressionStatement(identifier);
     // resolve
     _resolveNode(identifier);
     expect(identifier.staticElement, same(method));
@@ -912,14 +916,14 @@
     // set accessors
     String propName = "b";
     PropertyAccessorElement getter =
-        ElementFactory.getterElement(propName, false, _typeProvider.intType);
+        ElementFactory.getterElement(propName, true, _typeProvider.intType);
     PropertyAccessorElement setter =
-        ElementFactory.setterElement(propName, false, _typeProvider.intType);
+        ElementFactory.setterElement(propName, true, _typeProvider.intType);
     classA.accessors = <PropertyAccessorElement>[getter, setter];
     // prepare "A.b = null"
     SimpleIdentifier target = AstTestFactory.identifier3("A");
     target.staticElement = classA;
-    target.staticType = classA.type;
+    target.staticType = interfaceType(classA);
     PrefixedIdentifier identifier =
         AstTestFactory.identifier(target, AstTestFactory.identifier3(propName));
     AstTestFactory.assignmentExpression(
@@ -949,7 +953,7 @@
         ElementFactory.getterElement(getterName, false, _typeProvider.intType);
     classA.accessors = <PropertyAccessorElement>[getter];
     SimpleIdentifier target = AstTestFactory.identifier3("a");
-    target.staticType = classA.type;
+    target.staticType = interfaceType(classA);
     PropertyAccess access = AstTestFactory.propertyAccess2(target, getterName);
     _resolveNode(access);
     expect(access.propertyName.staticElement, same(getter));
@@ -971,7 +975,8 @@
         ElementFactory.getterElement(getterName, false, _typeProvider.intType);
     classA.accessors = <PropertyAccessorElement>[getter];
     SuperExpression target = AstTestFactory.superExpression();
-    target.staticType = ElementFactory.classElement("B", classA.type).type;
+    target.staticType =
+        interfaceType(ElementFactory.classElement("B", interfaceType(classA)));
     PropertyAccess access = AstTestFactory.propertyAccess2(target, getterName);
     AstTestFactory.methodDeclaration2(
         null,
@@ -993,7 +998,7 @@
         ElementFactory.setterElement(setterName, false, _typeProvider.intType);
     classA.accessors = <PropertyAccessorElement>[setter];
     ThisExpression target = AstTestFactory.thisExpression();
-    target.staticType = classA.type;
+    target.staticType = interfaceType(classA);
     PropertyAccess access = AstTestFactory.propertyAccess2(target, setterName);
     AstTestFactory.assignmentExpression(
         access, TokenType.EQ, AstTestFactory.integer(0));
@@ -1049,7 +1054,7 @@
         ElementFactory.constructorElement2(superclass, null);
     superclass.constructors = <ConstructorElement>[superConstructor];
     ClassElementImpl subclass =
-        ElementFactory.classElement("B", superclass.type);
+        ElementFactory.classElement("B", interfaceType(superclass));
     ConstructorElementImpl subConstructor =
         ElementFactory.constructorElement2(subclass, null);
     subclass.constructors = <ConstructorElement>[subConstructor];
@@ -1072,7 +1077,7 @@
     superConstructor.parameters = <ParameterElement>[parameter];
     superclass.constructors = <ConstructorElement>[superConstructor];
     ClassElementImpl subclass =
-        ElementFactory.classElement("B", superclass.type);
+        ElementFactory.classElement("B", interfaceType(superclass));
     ConstructorElementImpl subConstructor =
         ElementFactory.constructorElement2(subclass, null);
     subclass.constructors = <ConstructorElement>[subConstructor];
diff --git a/pkg/analyzer/test/generated/elements_types_mixin.dart b/pkg/analyzer/test/generated/elements_types_mixin.dart
new file mode 100644
index 0000000..fe87f3d
--- /dev/null
+++ b/pkg/analyzer/test/generated/elements_types_mixin.dart
@@ -0,0 +1,206 @@
+// 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/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/generated/resolver.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:meta/meta.dart';
+
+mixin ElementsTypesMixin {
+  DynamicTypeImpl get dynamicType => typeProvider.dynamicType;
+
+  TypeProvider get typeProvider;
+
+  ClassElementImpl class_({
+    @required String name,
+    bool isAbstract = false,
+    InterfaceType superType,
+    List<TypeParameterElement> typeParameters = const [],
+    List<InterfaceType> interfaces = const [],
+    List<InterfaceType> mixins = const [],
+    List<MethodElement> methods = const [],
+  }) {
+    var element = ClassElementImpl(name, 0);
+    element.typeParameters = typeParameters;
+    element.supertype = superType ?? typeProvider.objectType;
+    element.interfaces = interfaces;
+    element.mixins = mixins;
+    element.methods = methods;
+    return element;
+  }
+
+  FunctionType functionType({
+    List<TypeParameterElement> typeFormals,
+    List<DartType> required,
+    List<DartType> optional,
+    Map<String, DartType> named,
+    DartType returns,
+    NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
+  }) {
+    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>[],
+      parameters,
+      nullabilitySuffix: nullabilitySuffix,
+    );
+  }
+
+  FunctionType functionTypeAliasType(
+    FunctionTypeAliasElement element, {
+    List<DartType> typeArguments = const [],
+    NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
+  }) {
+    return element.instantiate2(
+      typeArguments: typeArguments,
+      nullabilitySuffix: nullabilitySuffix,
+    );
+  }
+
+  DartType futureType(DartType T) {
+    var futureElement = typeProvider.futureElement;
+    return interfaceType(futureElement, typeArguments: [T]);
+  }
+
+  GenericFunctionTypeElementImpl genericFunctionType({
+    List<TypeParameterElement> typeParameters,
+    List<ParameterElement> parameters,
+    DartType returnType,
+  }) {
+    var result = GenericFunctionTypeElementImpl.forOffset(0);
+    result.typeParameters = typeParameters;
+    result.parameters = parameters;
+    result.returnType = returnType ?? typeProvider.voidType;
+    return result;
+  }
+
+  GenericTypeAliasElementImpl genericTypeAlias({
+    @required String name,
+    List<TypeParameterElement> typeParameters = const [],
+    @required GenericFunctionTypeElement function,
+  }) {
+    return GenericTypeAliasElementImpl(name, 0)
+      ..typeParameters = typeParameters
+      ..function = function;
+  }
+
+  InterfaceType interfaceType(
+    ClassElement element, {
+    List<DartType> typeArguments = const [],
+    NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
+  }) {
+    return InterfaceTypeImpl.explicit(
+      element,
+      typeArguments,
+      nullabilitySuffix: nullabilitySuffix,
+    );
+  }
+
+  MethodElement method(
+    String name,
+    DartType returnType, {
+    bool isStatic = false,
+    List<TypeParameterElement> typeFormals = const [],
+    List<ParameterElement> parameters = const [],
+  }) {
+    var element = MethodElementImpl(name, 0)
+      ..isStatic = isStatic
+      ..parameters = parameters
+      ..returnType = returnType
+      ..typeParameters = typeFormals;
+    element.type = _typeOfExecutableElement(element);
+    return element;
+  }
+
+  ParameterElement namedParameter(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);
+    parameter.parameterKind = ParameterKind.POSITIONAL;
+    parameter.type = type;
+    return parameter;
+  }
+
+  ParameterElement requiredParameter(String name, {@required DartType type}) {
+    var parameter = ParameterElementImpl(name, 0);
+    parameter.parameterKind = ParameterKind.REQUIRED;
+    parameter.type = type;
+    return parameter;
+  }
+
+  TypeParameterElementImpl typeParameter(String name, {DartType bound}) {
+    var element = TypeParameterElementImpl.synthetic(name);
+    element.bound = bound;
+    return element;
+  }
+
+  TypeParameterTypeImpl typeParameterType(
+    TypeParameterElement element, {
+    NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
+  }) {
+    return TypeParameterTypeImpl(
+      element,
+      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
index 881eb2c..2b47aa3 100644
--- a/pkg/analyzer/test/generated/inheritance_manager_test.dart
+++ b/pkg/analyzer/test/generated/inheritance_manager_test.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';
@@ -68,7 +69,8 @@
     PropertyAccessorElement getterG =
         ElementFactory.getterElement(getterName, false, _typeProvider.intType);
     classA.accessors = <PropertyAccessorElement>[getterG];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", _interfaceType(classA));
     Map<String, ExecutableElement> mapB =
         _inheritanceManager.getMembersInheritedFromClasses(classB);
     Map<String, ExecutableElement> mapA =
@@ -88,7 +90,7 @@
         ElementFactory.getterElement(getterName, false, _typeProvider.intType);
     classA.accessors = <PropertyAccessorElement>[getterG];
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.interfaces = <InterfaceType>[classA.type];
+    classB.interfaces = <InterfaceType>[_interfaceType(classA)];
     Map<String, ExecutableElement> mapB =
         _inheritanceManager.getMembersInheritedFromClasses(classB);
     Map<String, ExecutableElement> mapA =
@@ -108,7 +110,7 @@
         ElementFactory.getterElement(getterName, false, _typeProvider.intType);
     classA.accessors = <PropertyAccessorElement>[getterG];
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.mixins = <InterfaceType>[classA.type];
+    classB.mixins = <InterfaceType>[_interfaceType(classA)];
     Map<String, ExecutableElement> mapB =
         _inheritanceManager.getMembersInheritedFromClasses(classB);
     Map<String, ExecutableElement> mapA =
@@ -137,7 +139,7 @@
         ElementFactory.methodElement(methodName, _typeProvider.intType);
     classA.methods = <MethodElement>[methodM];
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.supertype = classA.type;
+    classB.supertype = _interfaceType(classA);
     Map<String, ExecutableElement> mapB =
         _inheritanceManager.getMembersInheritedFromClasses(classB);
     Map<String, ExecutableElement> mapA =
@@ -157,7 +159,7 @@
         ElementFactory.methodElement(methodName, _typeProvider.intType);
     classA.methods = <MethodElement>[methodM];
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.interfaces = <InterfaceType>[classA.type];
+    classB.interfaces = <InterfaceType>[_interfaceType(classA)];
     Map<String, ExecutableElement> mapB =
         _inheritanceManager.getMembersInheritedFromClasses(classB);
     Map<String, ExecutableElement> mapA =
@@ -177,7 +179,7 @@
         ElementFactory.methodElement(methodName, _typeProvider.intType);
     classA.methods = <MethodElement>[methodM];
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.mixins = <InterfaceType>[classA.type];
+    classB.mixins = <InterfaceType>[_interfaceType(classA)];
     Map<String, ExecutableElement> mapB =
         _inheritanceManager.getMembersInheritedFromClasses(classB);
     Map<String, ExecutableElement> mapA =
@@ -202,7 +204,10 @@
         ElementFactory.methodElement(methodName, _typeProvider.intType);
     classA2.methods = <MethodElement>[methodA2M];
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.mixins = <InterfaceType>[classA1.type, classA2.type];
+    classB.mixins = <InterfaceType>[
+      _interfaceType(classA1),
+      _interfaceType(classA2)
+    ];
     Map<String, ExecutableElement> mapB =
         _inheritanceManager.getMembersInheritedFromClasses(classB);
     expect(mapB[methodName], same(methodA2M));
@@ -217,7 +222,8 @@
     PropertyAccessorElement getterG =
         ElementFactory.getterElement(getterName, false, _typeProvider.intType);
     classA.accessors = <PropertyAccessorElement>[getterG];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", _interfaceType(classA));
     Map<String, ExecutableElement> mapB =
         _inheritanceManager.getMembersInheritedFromInterfaces(classB);
     Map<String, ExecutableElement> mapA =
@@ -237,7 +243,7 @@
         ElementFactory.getterElement(getterName, false, _typeProvider.intType);
     classA.accessors = <PropertyAccessorElement>[getterG];
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.interfaces = <InterfaceType>[classA.type];
+    classB.interfaces = <InterfaceType>[_interfaceType(classA)];
     Map<String, ExecutableElement> mapB =
         _inheritanceManager.getMembersInheritedFromInterfaces(classB);
     Map<String, ExecutableElement> mapA =
@@ -257,7 +263,7 @@
         ElementFactory.getterElement(getterName, false, _typeProvider.intType);
     classA.accessors = <PropertyAccessorElement>[getterG];
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.mixins = <InterfaceType>[classA.type];
+    classB.mixins = <InterfaceType>[_interfaceType(classA)];
     Map<String, ExecutableElement> mapB =
         _inheritanceManager.getMembersInheritedFromInterfaces(classB);
     Map<String, ExecutableElement> mapA =
@@ -279,10 +285,11 @@
     classA.fields = <FieldElement>[fieldF];
     classA.accessors = <PropertyAccessorElement>[fieldF.getter, fieldF.setter];
 
-    ClassElementImpl classB = ElementFactory.classElement('B', classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement('B', _interfaceType(classA));
 
     ClassElementImpl classC = ElementFactory.classElement2('C');
-    classC.mixins = <InterfaceType>[classB.type];
+    classC.mixins = <InterfaceType>[_interfaceType(classB)];
 
     Map<String, ExecutableElement> mapC =
         _inheritanceManager.getMembersInheritedFromInterfaces(classC);
@@ -309,7 +316,8 @@
     MethodElement methodM =
         ElementFactory.methodElement(methodName, _typeProvider.intType);
     classA.methods = <MethodElement>[methodM];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", _interfaceType(classA));
     Map<String, ExecutableElement> mapB =
         _inheritanceManager.getMembersInheritedFromInterfaces(classB);
     Map<String, ExecutableElement> mapA =
@@ -329,7 +337,7 @@
         ElementFactory.methodElement(methodName, _typeProvider.intType);
     classA.methods = <MethodElement>[methodM];
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.interfaces = <InterfaceType>[classA.type];
+    classB.interfaces = <InterfaceType>[_interfaceType(classA)];
     Map<String, ExecutableElement> mapB =
         _inheritanceManager.getMembersInheritedFromInterfaces(classB);
     Map<String, ExecutableElement> mapA =
@@ -349,7 +357,7 @@
         ElementFactory.methodElement(methodName, _typeProvider.intType);
     classA.methods = <MethodElement>[methodM];
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.mixins = <InterfaceType>[classA.type];
+    classB.mixins = <InterfaceType>[_interfaceType(classA)];
     Map<String, ExecutableElement> mapB =
         _inheritanceManager.getMembersInheritedFromInterfaces(classB);
     Map<String, ExecutableElement> mapA =
@@ -375,7 +383,10 @@
         ElementFactory.methodElement(methodName2, _typeProvider.intType);
     classI2.methods = <MethodElement>[methodM2];
     ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.interfaces = <InterfaceType>[classI1.type, classI2.type];
+    classA.interfaces = <InterfaceType>[
+      _interfaceType(classI1),
+      _interfaceType(classI2)
+    ];
     Map<String, ExecutableElement> mapA =
         _inheritanceManager.getMembersInheritedFromInterfaces(classA);
     expect(mapA.length, _numOfMembersInObject + 2);
@@ -399,7 +410,10 @@
         accessorName, false, _typeProvider.numType);
     classI2.accessors = <PropertyAccessorElement>[getter2];
     ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.interfaces = <InterfaceType>[classI1.type, classI2.type];
+    classA.interfaces = <InterfaceType>[
+      _interfaceType(classI1),
+      _interfaceType(classI2)
+    ];
     Map<String, ExecutableElement> mapA =
         _inheritanceManager.getMembersInheritedFromInterfaces(classA);
     expect(mapA.length, _numOfMembersInObject + 1);
@@ -435,7 +449,10 @@
     methodM2.parameters = <ParameterElement>[parameter2];
     classI2.methods = <MethodElement>[methodM2];
     ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.interfaces = <InterfaceType>[classI1.type, classI2.type];
+    classA.interfaces = <InterfaceType>[
+      _interfaceType(classI1),
+      _interfaceType(classI2)
+    ];
     Map<String, ExecutableElement> mapA =
         _inheritanceManager.getMembersInheritedFromInterfaces(classA);
     expect(mapA.length, _numOfMembersInObject + 1);
@@ -461,7 +478,10 @@
         accessorName, false, _typeProvider.numType);
     classI2.accessors = <PropertyAccessorElement>[setter2];
     ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.interfaces = <InterfaceType>[classI1.type, classI2.type];
+    classA.interfaces = <InterfaceType>[
+      _interfaceType(classI1),
+      _interfaceType(classI2)
+    ];
     Map<String, ExecutableElement> mapA =
         _inheritanceManager.getMembersInheritedFromInterfaces(classA);
     expect(mapA.length, _numOfMembersInObject + 1);
@@ -483,33 +503,35 @@
     // class I3 { C get g; }
     // class D implements I1, I2, I3 {}
     ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement("C", classB.type);
+    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, classA.type);
+    PropertyAccessorElement getter1 = ElementFactory.getterElement(
+        accessorName, false, _interfaceType(classA));
     classI1.accessors = <PropertyAccessorElement>[getter1];
     ClassElementImpl classI2 = ElementFactory.classElement2("I2");
-    PropertyAccessorElement getter2 =
-        ElementFactory.getterElement(accessorName, false, classB.type);
+    PropertyAccessorElement getter2 = ElementFactory.getterElement(
+        accessorName, false, _interfaceType(classB));
     classI2.accessors = <PropertyAccessorElement>[getter2];
     ClassElementImpl classI3 = ElementFactory.classElement2("I3");
-    PropertyAccessorElement getter3 =
-        ElementFactory.getterElement(accessorName, false, classC.type);
+    PropertyAccessorElement getter3 = ElementFactory.getterElement(
+        accessorName, false, _interfaceType(classC));
     classI3.accessors = <PropertyAccessorElement>[getter3];
     ClassElementImpl classD = ElementFactory.classElement2("D");
     classD.interfaces = <InterfaceType>[
-      classI1.type,
-      classI2.type,
-      classI3.type
+      _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, classC.type);
+    syntheticAccessor = ElementFactory.getterElement(
+        accessorName, false, _interfaceType(classC));
     expect(mapD[accessorName].type, syntheticAccessor.type);
   }
 
@@ -524,15 +546,17 @@
     // class I3 { dynamic m(C c); }
     // class D implements I1, I2, I3 {}
     ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement("C", classB.type);
+    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 = classA.type;
+    parameter1.type = _interfaceType(classA);
     parameter1.parameterKind = ParameterKind.REQUIRED;
     methodM1.parameters = <ParameterElement>[parameter1];
     classI1.methods = <MethodElement>[methodM1];
@@ -541,7 +565,7 @@
         ElementFactory.methodElement(methodName, _typeProvider.dynamicType);
     ParameterElementImpl parameter2 =
         new ParameterElementImpl.forNode(AstTestFactory.identifier3("a0"));
-    parameter2.type = classB.type;
+    parameter2.type = _interfaceType(classB);
     parameter2.parameterKind = ParameterKind.REQUIRED;
     methodM2.parameters = <ParameterElement>[parameter2];
     classI2.methods = <MethodElement>[methodM2];
@@ -550,22 +574,22 @@
         ElementFactory.methodElement(methodName, _typeProvider.dynamicType);
     ParameterElementImpl parameter3 =
         new ParameterElementImpl.forNode(AstTestFactory.identifier3("a0"));
-    parameter3.type = classC.type;
+    parameter3.type = _interfaceType(classC);
     parameter3.parameterKind = ParameterKind.REQUIRED;
     methodM3.parameters = <ParameterElement>[parameter3];
     classI3.methods = <MethodElement>[methodM3];
     ClassElementImpl classD = ElementFactory.classElement2("D");
     classD.interfaces = <InterfaceType>[
-      classI1.type,
-      classI2.type,
-      classI3.type
+      _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, [classA.type]);
+        methodName, _typeProvider.dynamicType, [_interfaceType(classA)]);
     expect(mapD[methodName].type, syntheticMethod.type);
   }
 
@@ -580,33 +604,35 @@
     // class I3 { set s(C); }
     // class D implements I1, I2, I3 {}
     ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement("C", classB.type);
+    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, classA.type);
+    PropertyAccessorElement setter1 = ElementFactory.setterElement(
+        accessorName, false, _interfaceType(classA));
     classI1.accessors = <PropertyAccessorElement>[setter1];
     ClassElementImpl classI2 = ElementFactory.classElement2("I2");
-    PropertyAccessorElement setter2 =
-        ElementFactory.setterElement(accessorName, false, classB.type);
+    PropertyAccessorElement setter2 = ElementFactory.setterElement(
+        accessorName, false, _interfaceType(classB));
     classI2.accessors = <PropertyAccessorElement>[setter2];
     ClassElementImpl classI3 = ElementFactory.classElement2("I3");
-    PropertyAccessorElement setter3 =
-        ElementFactory.setterElement(accessorName, false, classC.type);
+    PropertyAccessorElement setter3 = ElementFactory.setterElement(
+        accessorName, false, _interfaceType(classC));
     classI3.accessors = <PropertyAccessorElement>[setter3];
     ClassElementImpl classD = ElementFactory.classElement2("D");
     classD.interfaces = <InterfaceType>[
-      classI1.type,
-      classI2.type,
-      classI3.type
+      _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, classA.type);
+    syntheticAccessor = ElementFactory.setterElement(
+        accessorName, false, _interfaceType(classA));
     syntheticAccessor.returnType = VoidTypeImpl.instance;
     expect(mapD["$accessorName="].type, syntheticAccessor.type);
   }
@@ -632,7 +658,10 @@
     methodM2.parameters = <ParameterElement>[parameter1];
     classI2.methods = <MethodElement>[methodM2];
     ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.interfaces = <InterfaceType>[classI1.type, classI2.type];
+    classA.interfaces = <InterfaceType>[
+      _interfaceType(classI1),
+      _interfaceType(classI2)
+    ];
     Map<String, ExecutableElement> mapA =
         _inheritanceManager.getMembersInheritedFromInterfaces(classA);
     expect(mapA.length, _numOfMembersInObject + 1);
@@ -675,9 +704,9 @@
     classI3.methods = <MethodElement>[methodM3];
     ClassElementImpl classA = ElementFactory.classElement2("A");
     classA.interfaces = <InterfaceType>[
-      classI1.type,
-      classI2.type,
-      classI3.type
+      _interfaceType(classI1),
+      _interfaceType(classI2),
+      _interfaceType(classI3)
     ];
     Map<String, ExecutableElement> mapA =
         _inheritanceManager.getMembersInheritedFromInterfaces(classA);
@@ -726,10 +755,10 @@
     classI4.methods = <MethodElement>[methodM4];
     ClassElementImpl classA = ElementFactory.classElement2("A");
     classA.interfaces = <InterfaceType>[
-      classI1.type,
-      classI2.type,
-      classI3.type,
-      classI4.type
+      _interfaceType(classI1),
+      _interfaceType(classI2),
+      _interfaceType(classI3),
+      _interfaceType(classI4),
     ];
     Map<String, ExecutableElement> mapA =
         _inheritanceManager.getMembersInheritedFromInterfaces(classA);
@@ -749,10 +778,11 @@
     classA.fields = <FieldElement>[fieldF];
     classA.accessors = <PropertyAccessorElement>[fieldF.getter, fieldF.setter];
 
-    ClassElementImpl classB = ElementFactory.classElement('B', classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement('B', _interfaceType(classA));
 
     ClassElementImpl classC = ElementFactory.classElement2('C');
-    classC.mixins = <InterfaceType>[classB.type];
+    classC.mixins = <InterfaceType>[_interfaceType(classB)];
 
     Map<String, ExecutableElement> mapC =
         _inheritanceManager.getMembersInheritedFromClasses(classC);
@@ -767,7 +797,7 @@
         ElementFactory.getterElement(getterName, false, _typeProvider.intType);
     classA.accessors = <PropertyAccessorElement>[getterG];
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.interfaces = <InterfaceType>[classA.type];
+    classB.interfaces = <InterfaceType>[_interfaceType(classA)];
     expect(_inheritanceManager.lookupInheritance(classB, getterName),
         same(getterG));
   }
@@ -780,7 +810,7 @@
         ElementFactory.methodElement(methodName, _typeProvider.intType);
     classA.methods = <MethodElement>[methodM];
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.interfaces = <InterfaceType>[classA.type];
+    classB.interfaces = <InterfaceType>[_interfaceType(classA)];
     expect(_inheritanceManager.lookupInheritance(classB, methodName),
         same(methodM));
   }
@@ -793,7 +823,7 @@
         ElementFactory.setterElement(setterName, false, _typeProvider.intType);
     classA.accessors = <PropertyAccessorElement>[setterS];
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.interfaces = <InterfaceType>[classA.type];
+    classB.interfaces = <InterfaceType>[_interfaceType(classA)];
     expect(_inheritanceManager.lookupInheritance(classB, "$setterName="),
         same(setterS));
   }
@@ -807,14 +837,14 @@
     (methodM as MethodElementImpl).isStatic = true;
     classA.methods = <MethodElement>[methodM];
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.interfaces = <InterfaceType>[classA.type];
+    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>[classA.type];
+    classA.interfaces = <InterfaceType>[_interfaceType(classA)];
     expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull);
   }
 
@@ -822,8 +852,8 @@
   void test_lookupInheritance_interfaces_infiniteLoop2() {
     ClassElementImpl classA = ElementFactory.classElement2("A");
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classA.interfaces = <InterfaceType>[classB.type];
-    classB.interfaces = <InterfaceType>[classA.type];
+    classA.interfaces = <InterfaceType>[_interfaceType(classB)];
+    classB.interfaces = <InterfaceType>[_interfaceType(classA)];
     expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull);
   }
 
@@ -839,9 +869,9 @@
     MethodElement methodM2 =
         ElementFactory.methodElement(methodName2, _typeProvider.intType);
     classI2.methods = <MethodElement>[methodM2];
-    classI2.interfaces = <InterfaceType>[classI1.type];
+    classI2.interfaces = <InterfaceType>[_interfaceType(classI1)];
     ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.interfaces = <InterfaceType>[classI2.type];
+    classA.interfaces = <InterfaceType>[_interfaceType(classI2)];
     expect(_inheritanceManager.lookupInheritance(classA, methodName1),
         same(methodM1));
     expect(_inheritanceManager.lookupInheritance(classA, methodName2),
@@ -856,7 +886,7 @@
         ElementFactory.getterElement(getterName, false, _typeProvider.intType);
     classA.accessors = <PropertyAccessorElement>[getterG];
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.mixins = <InterfaceType>[classA.type];
+    classB.mixins = <InterfaceType>[_interfaceType(classA)];
     expect(_inheritanceManager.lookupInheritance(classB, getterName),
         same(getterG));
   }
@@ -869,7 +899,7 @@
         ElementFactory.methodElement(methodName, _typeProvider.intType);
     classA.methods = <MethodElement>[methodM];
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.mixins = <InterfaceType>[classA.type];
+    classB.mixins = <InterfaceType>[_interfaceType(classA)];
     expect(_inheritanceManager.lookupInheritance(classB, methodName),
         same(methodM));
   }
@@ -882,7 +912,7 @@
         ElementFactory.setterElement(setterName, false, _typeProvider.intType);
     classA.accessors = <PropertyAccessorElement>[setterS];
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.mixins = <InterfaceType>[classA.type];
+    classB.mixins = <InterfaceType>[_interfaceType(classA)];
     expect(_inheritanceManager.lookupInheritance(classB, "$setterName="),
         same(setterS));
   }
@@ -896,7 +926,7 @@
     (methodM as MethodElementImpl).isStatic = true;
     classA.methods = <MethodElement>[methodM];
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.mixins = <InterfaceType>[classA.type];
+    classB.mixins = <InterfaceType>[_interfaceType(classA)];
     expect(_inheritanceManager.lookupInheritance(classB, methodName), isNull);
   }
 
@@ -913,7 +943,8 @@
     PropertyAccessorElement getterG =
         ElementFactory.getterElement(getterName, false, _typeProvider.intType);
     classA.accessors = <PropertyAccessorElement>[getterG];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", _interfaceType(classA));
     expect(_inheritanceManager.lookupInheritance(classB, getterName),
         same(getterG));
   }
@@ -921,7 +952,7 @@
   @deprecated
   void test_lookupInheritance_superclass_infiniteLoop() {
     ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.supertype = classA.type;
+    classA.supertype = _interfaceType(classA);
     expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull);
   }
 
@@ -929,8 +960,8 @@
   void test_lookupInheritance_superclass_infiniteLoop2() {
     ClassElementImpl classA = ElementFactory.classElement2("A");
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classA.supertype = classB.type;
-    classB.supertype = classA.type;
+    classA.supertype = _interfaceType(classB);
+    classB.supertype = _interfaceType(classA);
     expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull);
   }
 
@@ -941,7 +972,8 @@
     MethodElement methodM =
         ElementFactory.methodElement(methodName, _typeProvider.intType);
     classA.methods = <MethodElement>[methodM];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", _interfaceType(classA));
     expect(_inheritanceManager.lookupInheritance(classB, methodName),
         same(methodM));
   }
@@ -953,7 +985,8 @@
     PropertyAccessorElement setterS =
         ElementFactory.setterElement(setterName, false, _typeProvider.intType);
     classA.accessors = <PropertyAccessorElement>[setterS];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", _interfaceType(classA));
     expect(_inheritanceManager.lookupInheritance(classB, "$setterName="),
         same(setterS));
   }
@@ -966,7 +999,8 @@
         ElementFactory.methodElement(methodName, _typeProvider.intType);
     (methodM as MethodElementImpl).isStatic = true;
     classA.methods = <MethodElement>[methodM];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", _interfaceType(classA));
     expect(_inheritanceManager.lookupInheritance(classB, methodName), isNull);
   }
 
@@ -1056,7 +1090,8 @@
     MethodElementImpl methodMinA =
         ElementFactory.methodElement(methodName, _typeProvider.intType);
     classA.methods = <MethodElement>[methodMinA];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", _interfaceType(classA));
     MethodElementImpl methodMinB =
         ElementFactory.methodElement(methodName, _typeProvider.intType);
     classB.methods = <MethodElement>[methodMinB];
@@ -1073,7 +1108,7 @@
         ElementFactory.methodElement(methodName, _typeProvider.intType);
     classA.methods = <MethodElement>[methodMinA];
     ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.interfaces = <InterfaceType>[classA.type];
+    classB.interfaces = <InterfaceType>[_interfaceType(classA)];
     MethodElementImpl methodMinB =
         ElementFactory.methodElement(methodName, _typeProvider.intType);
     classB.methods = <MethodElement>[methodMinB];
@@ -1094,7 +1129,10 @@
         ElementFactory.methodElement(methodName, _typeProvider.doubleType);
     classB.methods = <MethodElement>[methodMinB];
     ClassElementImpl classC = ElementFactory.classElement2("C");
-    classC.interfaces = <InterfaceType>[classA.type, classB.type];
+    classC.interfaces = <InterfaceType>[
+      _interfaceType(classA),
+      _interfaceType(classB)
+    ];
     MethodElementImpl methodMinC =
         ElementFactory.methodElement(methodName, _typeProvider.numType);
     classC.methods = <MethodElement>[methodMinC];
@@ -1120,4 +1158,11 @@
     _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 c77fa3e0..165a105 100644
--- a/pkg/analyzer/test/generated/invalid_code_test.dart
+++ b/pkg/analyzer/test/generated/invalid_code_test.dart
@@ -178,6 +178,12 @@
 ''');
   }
 
+  test_fuzz_38091() async {
+    // https://github.com/dart-lang/sdk/issues/38091
+    // this caused an infinite loop in parser recovery
+    await _assertCanBeAnalyzed(r'c(=k(<)>');
+  }
+
   test_genericFunction_asTypeArgument_ofUnresolvedClass() async {
     await _assertCanBeAnalyzed(r'''
 C<int Function()> c;
@@ -230,6 +236,29 @@
     ..contextFeatures = new FeatureSet.forTesting(
         sdkVersion: '2.3.0', additionalFeatures: [Feature.extension_methods]);
 
+  test_extensionOverrideInAnnotationContext() async {
+    await _assertCanBeAnalyzed('''
+class R {
+  const R(int x);
+}
+
+@R(E(null).f())
+extension E on Object {
+  int f() => 0;
+}
+''');
+  }
+
+  test_extensionOverrideInConstContext() async {
+    await _assertCanBeAnalyzed('''
+extension E on Object {
+  int f() => 0;
+}
+
+const e = E(null).f();
+''');
+  }
+
   test_fuzz_14() async {
     // This crashes because parser produces `ConstructorDeclaration`.
     // So, we try to create `ConstructorElement` for it, and it wants
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 42e45f2..805d5c7 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -2582,6 +2582,12 @@
     expect(indexExpression.toSource(), '?..[27]');
   }
 
+  void test_cascade_withNullCheck_invalid() {
+    parseCompilationUnit('main() { a..[27]?..x; }', errors: [
+      expectedError(ParserErrorCode.NULL_AWARE_CASCADE_OUT_OF_ORDER, 16, 3),
+    ]);
+  }
+
   void test_cascade_withNullCheck_methodInvocation() {
     var unit = parseCompilationUnit('main() { a?..foo(); }');
     FunctionDeclaration funct = unit.declarations[0];
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 0b7c771..691b596 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -16,7 +16,6 @@
 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/dart/element/type_provider.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
@@ -31,6 +30,7 @@
 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';
@@ -38,13 +38,11 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(AnalysisDeltaTest);
     defineReflectiveTests(ChangeSetTest);
     defineReflectiveTests(EnclosedScopeTest);
     defineReflectiveTests(ErrorResolverTest);
     defineReflectiveTests(LibraryImportScopeTest);
     defineReflectiveTests(LibraryScopeTest);
-    defineReflectiveTests(NonNullableTypeProviderTest);
     defineReflectiveTests(PrefixedNamespaceTest);
     defineReflectiveTests(ScopeTest);
     defineReflectiveTests(StrictModeTest);
@@ -63,46 +61,6 @@
 }
 
 @reflectiveTest
-class AnalysisDeltaTest extends EngineTestCase {
-  TestSource source1 = new TestSource('/1.dart');
-  TestSource source2 = new TestSource('/2.dart');
-  TestSource source3 = new TestSource('/3.dart');
-
-  void test_getAddedSources() {
-    AnalysisDelta delta = new AnalysisDelta();
-    delta.setAnalysisLevel(source1, AnalysisLevel.ALL);
-    delta.setAnalysisLevel(source2, AnalysisLevel.ERRORS);
-    delta.setAnalysisLevel(source3, AnalysisLevel.NONE);
-    List<Source> addedSources = delta.addedSources;
-    expect(addedSources, hasLength(2));
-    expect(addedSources, unorderedEquals([source1, source2]));
-  }
-
-  void test_getAnalysisLevels() {
-    AnalysisDelta delta = new AnalysisDelta();
-    expect(delta.analysisLevels.length, 0);
-  }
-
-  void test_setAnalysisLevel() {
-    AnalysisDelta delta = new AnalysisDelta();
-    delta.setAnalysisLevel(source1, AnalysisLevel.ALL);
-    delta.setAnalysisLevel(source2, AnalysisLevel.ERRORS);
-    Map<Source, AnalysisLevel> levels = delta.analysisLevels;
-    expect(levels.length, 2);
-    expect(levels[source1], AnalysisLevel.ALL);
-    expect(levels[source2], AnalysisLevel.ERRORS);
-  }
-
-  void test_toString() {
-    AnalysisDelta delta = new AnalysisDelta();
-    delta.setAnalysisLevel(new TestSource(), AnalysisLevel.ALL);
-    String result = delta.toString();
-    expect(result, isNotNull);
-    expect(result.isNotEmpty, isTrue);
-  }
-}
-
-@reflectiveTest
 class ChangeSetTest extends EngineTestCase {
   void test_changedContent() {
     TestSource source = new TestSource();
@@ -530,132 +488,6 @@
 }
 
 @reflectiveTest
-class NonNullableTypeProviderTest extends EngineTestCase {
-  void assertNonNullable(InterfaceType type) {
-    expect((type as TypeImpl).nullabilitySuffix, NullabilitySuffix.none);
-  }
-
-  void test_creation() {
-    //
-    // Create a mock library element with the types expected to be in dart:core.
-    // We cannot use either ElementFactory or TestTypeProvider (which uses
-    // ElementFactory) because we side-effect the elements in ways that would
-    // break other tests.
-    //
-    InterfaceType objectType = _classElement("Object", null).type;
-    InterfaceType boolType = _classElement("bool", objectType).type;
-    InterfaceType numType = _classElement("num", objectType).type;
-    InterfaceType deprecatedType = _classElement('Deprecated', objectType).type;
-    InterfaceType doubleType = _classElement("double", numType).type;
-    InterfaceType functionType = _classElement("Function", objectType).type;
-    InterfaceType futureType = _classElement("Future", objectType, ["T"]).type;
-    InterfaceType futureOrType =
-        _classElement("FutureOr", objectType, ["T"]).type;
-    InterfaceType intType = _classElement("int", numType).type;
-    InterfaceType iterableType =
-        _classElement("Iterable", objectType, ["T"]).type;
-    InterfaceType listType = _classElement("List", objectType, ["E"]).type;
-    InterfaceType mapType = _classElement("Map", objectType, ["K", "V"]).type;
-    InterfaceType nullType = _classElement('Null', objectType).type;
-    InterfaceType setType = _classElement("Set", objectType, ["E"]).type;
-    InterfaceType stackTraceType = _classElement("StackTrace", objectType).type;
-    InterfaceType streamType = _classElement("Stream", objectType, ["T"]).type;
-    InterfaceType stringType = _classElement("String", objectType).type;
-    InterfaceType symbolType = _classElement("Symbol", objectType).type;
-    InterfaceType typeType = _classElement("Type", objectType).type;
-    CompilationUnitElementImpl coreUnit = new CompilationUnitElementImpl();
-    coreUnit.types = <ClassElement>[
-      boolType.element,
-      deprecatedType.element,
-      doubleType.element,
-      functionType.element,
-      intType.element,
-      iterableType.element,
-      listType.element,
-      mapType.element,
-      nullType.element,
-      numType.element,
-      setType.element,
-      objectType.element,
-      stackTraceType.element,
-      stringType.element,
-      symbolType.element,
-      typeType.element
-    ];
-    coreUnit.source = new TestSource('dart:core');
-    coreUnit.librarySource = coreUnit.source;
-    CompilationUnitElementImpl asyncUnit = new CompilationUnitElementImpl();
-    asyncUnit.types = <ClassElement>[
-      futureType.element,
-      futureOrType.element,
-      streamType.element
-    ];
-    asyncUnit.source = new TestSource('dart:async');
-    asyncUnit.librarySource = asyncUnit.source;
-    LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode(
-        null, null, AstTestFactory.libraryIdentifier2(["dart.core"]), true);
-    coreLibrary.definingCompilationUnit = coreUnit;
-    LibraryElementImpl asyncLibrary = new LibraryElementImpl.forNode(
-        null, null, AstTestFactory.libraryIdentifier2(["dart.async"]), true);
-    asyncLibrary.definingCompilationUnit = asyncUnit;
-    //
-    // Create a type provider and ensure that it can return the expected types.
-    //
-    TypeProvider provider = new TypeProviderImpl(
-      coreLibrary,
-      asyncLibrary,
-      nullabilitySuffix: NullabilitySuffix.none,
-    );
-    assertNonNullable(provider.boolType);
-    expect(provider.bottomType, isNotNull);
-    assertNonNullable(provider.deprecatedType);
-    assertNonNullable(provider.doubleType);
-    expect(provider.dynamicType, isNotNull);
-    assertNonNullable(provider.functionType);
-    assertNonNullable(provider.futureType);
-    assertNonNullable(provider.futureOrType);
-    assertNonNullable(provider.intType);
-    assertNonNullable(provider.listType);
-    assertNonNullable(provider.mapType);
-    expect(provider.neverType, isNotNull);
-    assertNonNullable(provider.nullType);
-    assertNonNullable(provider.numType);
-    assertNonNullable(provider.objectType);
-    assertNonNullable(provider.stackTraceType);
-    assertNonNullable(provider.streamType);
-    assertNonNullable(provider.stringType);
-    assertNonNullable(provider.symbolType);
-    assertNonNullable(provider.typeType);
-  }
-
-  ClassElement _classElement(String typeName, InterfaceType superclassType,
-      [List<String> parameterNames]) {
-    ClassElementImpl element =
-        new ClassElementImpl.forNode(AstTestFactory.identifier3(typeName));
-    element.supertype = superclassType;
-    if (parameterNames != null) {
-      int count = parameterNames.length;
-      if (count > 0) {
-        List<TypeParameterElementImpl> typeParameters =
-            new List<TypeParameterElementImpl>(count);
-        List<TypeParameterTypeImpl> typeArguments =
-            new List<TypeParameterTypeImpl>(count);
-        for (int i = 0; i < count; i++) {
-          TypeParameterElementImpl typeParameter =
-              new TypeParameterElementImpl.forNode(
-                  AstTestFactory.identifier3(parameterNames[i]));
-          typeParameters[i] = typeParameter;
-          typeArguments[i] = new TypeParameterTypeImpl(typeParameter);
-          typeParameter.type = typeArguments[i];
-        }
-        element.typeParameters = typeParameters;
-      }
-    }
-    return element;
-  }
-}
-
-@reflectiveTest
 class PrefixedNamespaceTest extends DriverResolutionTest {
   void test_lookup_missing() {
     ClassElement element = ElementFactory.classElement2('A');
@@ -1332,7 +1164,7 @@
 
 @reflectiveTest
 class TypeResolverVisitorTest extends ParserTestCase
-    with ResourceProviderMixin {
+    with ResourceProviderMixin, ElementsTypesMixin {
   /**
    * The error listener to which errors will be reported.
    */
@@ -1353,6 +1185,8 @@
    */
   TypeResolverVisitor _visitor;
 
+  TypeProvider get typeProvider => _typeProvider;
+
   fail_visitConstructorDeclaration() async {
     _fail("Not yet tested");
     _listener.assertNoErrors();
@@ -1370,7 +1204,7 @@
     AstTestFactory.variableDeclarationList(
         null, AstTestFactory.typeName(type), [node]);
     //resolve(node);
-    expect(node.name.staticType, same(type.type));
+    expect(node.name.staticType, interfaceType(type));
     _listener.assertNoErrors();
   }
 
@@ -1818,7 +1652,7 @@
     exceptionParameter.staticElement =
         new LocalVariableElementImpl.forNode(exceptionParameter);
     _resolveCatchClause(
-        clause, exceptionElement.type, null, [exceptionElement]);
+        clause, interfaceType(exceptionElement), null, [exceptionElement]);
     _listener.assertNoErrors();
   }
 
@@ -1834,7 +1668,7 @@
     SimpleIdentifier stackTraceParameter = clause.stackTraceParameter;
     stackTraceParameter.staticElement =
         new LocalVariableElementImpl.forNode(stackTraceParameter);
-    _resolveCatchClause(clause, exceptionElement.type,
+    _resolveCatchClause(clause, interfaceType(exceptionElement),
         _typeProvider.stackTraceType, [exceptionElement]);
     _listener.assertNoErrors();
   }
@@ -1859,13 +1693,13 @@
         null, "A", null, extendsClause, withClause, implementsClause);
     declaration.name.staticElement = elementA;
     _resolveNode(declaration, [elementA, elementB, elementC, elementD]);
-    expect(elementA.supertype, elementB.type);
+    expect(elementA.supertype, interfaceType(elementB));
     List<InterfaceType> mixins = elementA.mixins;
     expect(mixins, hasLength(1));
-    expect(mixins[0], elementC.type);
+    expect(mixins[0], interfaceType(elementC));
     List<InterfaceType> interfaces = elementA.interfaces;
     expect(interfaces, hasLength(1));
-    expect(interfaces[0], elementD.type);
+    expect(interfaces[0], interfaceType(elementD));
     _listener.assertNoErrors();
   }
 
@@ -1886,7 +1720,7 @@
         null, "B", null, extendsClause, null, null);
     declaration.name.staticElement = elementB;
     _resolveNode(declaration, [elementA, elementB]);
-    expect(elementB.supertype, elementA.type);
+    expect(elementB.supertype, interfaceType(elementA));
     _listener.assertNoErrors();
   }
 
@@ -1958,10 +1792,10 @@
             null));
     declaration.name.staticElement = elementF;
     _resolveNode(declaration, [elementR, elementP]);
-    expect(declaration.returnType.type, elementR.type);
+    expect(declaration.returnType.type, interfaceType(elementR));
     SimpleFormalParameter parameter =
         declaration.functionExpression.parameters.parameters[0];
-    expect(parameter.type.type, elementP.type);
+    expect(parameter.type.type, interfaceType(elementP));
     _listener.assertNoErrors();
   }
 
@@ -1982,10 +1816,10 @@
             null));
     declaration.name.staticElement = elementF;
     _resolveNode(declaration, []);
-    expect(declaration.returnType.type, elementE.type);
+    expect(declaration.returnType.type, typeParameterType(elementE));
     SimpleFormalParameter parameter =
         declaration.functionExpression.parameters.parameters[0];
-    expect(parameter.type.type, elementE.type);
+    expect(parameter.type.type, typeParameterType(elementE));
     _listener.assertNoErrors();
   }
 
@@ -2022,10 +1856,10 @@
 
     _resolveNode(fNode, [elementR, elementP]);
 
-    expect(fNode.returnType.type, elementR.type);
-    expect(gType.returnType, elementR.type);
-    expect(gNode.returnType.type, elementR.type);
-    expect(pNode.type.type, elementP.type);
+    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();
   }
@@ -2063,10 +1897,10 @@
 
     _resolveNode(fNode, [elementR]);
 
-    expect(fNode.returnType.type, elementR.type);
-    expect(gType.returnType, elementR.type);
-    expect(gNode.returnType.type, elementR.type);
-    expect(eNode.type.type, elementE.type);
+    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();
   }
@@ -2094,9 +1928,9 @@
         ]));
     declaration.name.staticElement = elementM;
     _resolveNode(declaration, [elementA, elementR, elementP]);
-    expect(declaration.returnType.type, elementR.type);
+    expect(declaration.returnType.type, interfaceType(elementR));
     SimpleFormalParameter parameter = declaration.parameters.parameters[0];
-    expect(parameter.type.type, elementP.type);
+    expect(parameter.type.type, interfaceType(elementP));
     _listener.assertNoErrors();
   }
 
@@ -2121,9 +1955,9 @@
         ]));
     declaration.name.staticElement = elementM;
     _resolveNode(declaration, [elementA]);
-    expect(declaration.returnType.type, elementE.type);
+    expect(declaration.returnType.type, typeParameterType(elementE));
     SimpleFormalParameter parameter = declaration.parameters.parameters[0];
-    expect(parameter.type.type, elementE.type);
+    expect(parameter.type.type, typeParameterType(elementE));
     _listener.assertNoErrors();
   }
 
@@ -2154,7 +1988,7 @@
     TypeName typeName = AstTestFactory.typeName(classA);
     typeName.type = null;
     _resolveNode(typeName, [classA]);
-    expect(typeName.type, classA.type);
+    expect(typeName.type, interfaceType(classA));
     _listener.assertNoErrors();
   }
 
@@ -2179,7 +2013,7 @@
     expect(resultType.element, same(classA));
     List<DartType> resultArguments = resultType.typeArguments;
     expect(resultArguments, hasLength(1));
-    expect(resultArguments[0], classB.type);
+    expect(resultArguments[0], interfaceType(classB));
     _listener.assertNoErrors();
   }
 
diff --git a/pkg/analyzer/test/generated/resolver_test_case.dart b/pkg/analyzer/test/generated/resolver_test_case.dart
index fdb3b15..aa995d1 100644
--- a/pkg/analyzer/test/generated/resolver_test_case.dart
+++ b/pkg/analyzer/test/generated/resolver_test_case.dart
@@ -20,7 +20,7 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/file_system/file_system.dart';
-import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
+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/sdk.dart';
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index de9c1f3..c9246a0 100644
--- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/element.dart';
@@ -25,6 +26,7 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'elements_types_mixin.dart';
 import 'resolver_test_case.dart';
 import 'test_analysis_context.dart';
 import 'test_support.dart';
@@ -172,7 +174,9 @@
           typeFormals: '[S]',
           identifierType: 'void Function<S>(S)');
 
-      typeS = type.typeFormals[0].type;
+      typeS = type.typeFormals[0].instantiate(
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
       type = type.instantiate([DynamicTypeImpl.instance]);
       expect(type.toString(), 'void Function(dynamic)');
       expect(type.typeParameters.toString(), '[S]');
@@ -227,7 +231,8 @@
 }
 
 @reflectiveTest
-class StaticTypeAnalyzerTest extends EngineTestCase with ResourceProviderMixin {
+class StaticTypeAnalyzerTest extends EngineTestCase
+    with ResourceProviderMixin, ElementsTypesMixin {
   /**
    * The error listener to which errors will be reported.
    */
@@ -248,6 +253,8 @@
    */
   TypeProvider _typeProvider;
 
+  TypeProvider get typeProvider => _typeProvider;
+
   /**
    * The type system used to analyze the test cases.
    */
@@ -279,22 +286,26 @@
     // class Derived<T> extends Future<T> { ... }
     ClassElementImpl derivedClass =
         ElementFactory.classElement2('Derived', ['T']);
-    derivedClass.supertype = _typeProvider.futureType
-        .instantiate([derivedClass.typeParameters[0].type]);
+    derivedClass.supertype =
+        futureType(typeParameterType(derivedClass.typeParameters[0]));
     InterfaceType intType = _typeProvider.intType;
     DartType dynamicType = _typeProvider.dynamicType;
-    InterfaceType derivedIntType = derivedClass.type.instantiate([intType]);
+    InterfaceType derivedIntType =
+        interfaceType(derivedClass, typeArguments: [intType]);
     // flatten(Derived) = dynamic
     InterfaceType derivedDynamicType =
-        derivedClass.type.instantiate([dynamicType]);
+        interfaceType(derivedClass, typeArguments: [dynamicType]);
     expect(_flatten(derivedDynamicType), dynamicType);
     // flatten(Derived<int>) = int
     expect(_flatten(derivedIntType), intType);
     // flatten(Derived<Derived>) = Derived
-    expect(_flatten(derivedClass.type.instantiate([derivedDynamicType])),
+    expect(
+        _flatten(
+            interfaceType(derivedClass, typeArguments: [derivedDynamicType])),
         derivedDynamicType);
     // flatten(Derived<Derived<int>>) = Derived<int>
-    expect(_flatten(derivedClass.type.instantiate([derivedIntType])),
+    expect(
+        _flatten(interfaceType(derivedClass, typeArguments: [derivedIntType])),
         derivedIntType);
   }
 
@@ -303,13 +314,13 @@
     // class B extends A
     ClassElementImpl classA = ElementFactory.classElement2('A', []);
     ClassElementImpl classB = ElementFactory.classElement2('B', []);
-    classA.supertype = classB.type;
-    classB.supertype = classA.type;
+    classA.supertype = interfaceType(classB);
+    classB.supertype = interfaceType(classA);
     // flatten(A) = A and flatten(B) = B, since neither class contains Future
     // in its class hierarchy.  Even though there is a loop in the class
     // hierarchy, flatten() should terminate.
-    expect(_flatten(classA.type), classA.type);
-    expect(_flatten(classB.type), classB.type);
+    expect(_flatten(interfaceType(classA)), interfaceType(classA));
+    expect(_flatten(interfaceType(classB)), interfaceType(classB));
   }
 
   void test_flatten_related_derived_types() {
@@ -318,59 +329,52 @@
     // class Derived<T> extends Future<T>
     ClassElementImpl derivedClass =
         ElementFactory.classElement2('Derived', ['T']);
-    derivedClass.supertype = _typeProvider.futureType
-        .instantiate([derivedClass.typeParameters[0].type]);
-    InterfaceType derivedType = derivedClass.type;
+    derivedClass.supertype =
+        futureType(typeParameterType(derivedClass.typeParameters[0]));
     // class A extends Derived<int> implements Derived<num> { ... }
-    ClassElementImpl classA =
-        ElementFactory.classElement('A', derivedType.instantiate([intType]));
+    ClassElementImpl classA = ElementFactory.classElement(
+        'A', interfaceType(derivedClass, typeArguments: [intType]));
     classA.interfaces = <InterfaceType>[
-      derivedType.instantiate([numType])
+      interfaceType(derivedClass, typeArguments: [numType]),
     ];
     // class B extends Future<num> implements Future<int> { ... }
-    ClassElementImpl classB =
-        ElementFactory.classElement('B', derivedType.instantiate([numType]));
+    ClassElementImpl classB = ElementFactory.classElement(
+        'B', interfaceType(derivedClass, typeArguments: [numType]));
     classB.interfaces = <InterfaceType>[
-      derivedType.instantiate([intType])
+      interfaceType(derivedClass, typeArguments: [intType])
     ];
     // flatten(A) = flatten(B) = int, since int is more specific than num.
     // The code in flatten() that inhibits infinite recursion shouldn't be
     // fooled by the fact that Derived appears twice in the type hierarchy.
-    expect(_flatten(classA.type), intType);
-    expect(_flatten(classB.type), intType);
+    expect(_flatten(interfaceType(classA)), intType);
+    expect(_flatten(interfaceType(classB)), intType);
   }
 
   void test_flatten_related_types() {
-    InterfaceType futureType = _typeProvider.futureType;
     InterfaceType intType = _typeProvider.intType;
     InterfaceType numType = _typeProvider.numType;
     // class A extends Future<int> implements Future<num> { ... }
     ClassElementImpl classA =
-        ElementFactory.classElement('A', futureType.instantiate([intType]));
-    classA.interfaces = <InterfaceType>[
-      futureType.instantiate([numType])
-    ];
+        ElementFactory.classElement('A', _typeProvider.futureType2(intType));
+    classA.interfaces = <InterfaceType>[_typeProvider.futureType2(numType)];
     // class B extends Future<num> implements Future<int> { ... }
     ClassElementImpl classB =
-        ElementFactory.classElement('B', futureType.instantiate([numType]));
-    classB.interfaces = <InterfaceType>[
-      futureType.instantiate([intType])
-    ];
+        ElementFactory.classElement('B', _typeProvider.futureType2(numType));
+    classB.interfaces = <InterfaceType>[_typeProvider.futureType2(intType)];
     // flatten(A) = flatten(B) = int, since int is more specific than num.
-    expect(_flatten(classA.type), intType);
-    expect(_flatten(classB.type), intType);
+    expect(_flatten(interfaceType(classA)), intType);
+    expect(_flatten(interfaceType(classB)), intType);
   }
 
   void test_flatten_simple() {
     InterfaceType intType = _typeProvider.intType;
     DartType dynamicType = _typeProvider.dynamicType;
     InterfaceType futureDynamicType = _typeProvider.futureDynamicType;
-    InterfaceType futureIntType =
-        _typeProvider.futureType.instantiate([intType]);
+    InterfaceType futureIntType = _typeProvider.futureType2(intType);
     InterfaceType futureFutureDynamicType =
-        _typeProvider.futureType.instantiate([futureDynamicType]);
+        _typeProvider.futureType2(futureDynamicType);
     InterfaceType futureFutureIntType =
-        _typeProvider.futureType.instantiate([futureIntType]);
+        _typeProvider.futureType2(futureIntType);
     // flatten(int) = int
     expect(_flatten(intType), intType);
     // flatten(dynamic) = dynamic
@@ -386,25 +390,20 @@
   }
 
   void test_flatten_unrelated_types() {
-    InterfaceType futureType = _typeProvider.futureType;
     InterfaceType intType = _typeProvider.intType;
     InterfaceType stringType = _typeProvider.stringType;
     // class A extends Future<int> implements Future<String> { ... }
     ClassElementImpl classA =
-        ElementFactory.classElement('A', futureType.instantiate([intType]));
-    classA.interfaces = <InterfaceType>[
-      futureType.instantiate([stringType])
-    ];
+        ElementFactory.classElement('A', _typeProvider.futureType2(intType));
+    classA.interfaces = <InterfaceType>[_typeProvider.futureType2(stringType)];
     // class B extends Future<String> implements Future<int> { ... }
     ClassElementImpl classB =
-        ElementFactory.classElement('B', futureType.instantiate([stringType]));
-    classB.interfaces = <InterfaceType>[
-      futureType.instantiate([intType])
-    ];
+        ElementFactory.classElement('B', _typeProvider.futureType2(stringType));
+    classB.interfaces = <InterfaceType>[_typeProvider.futureType2(intType)];
     // flatten(A) = A and flatten(B) = B, since neither string nor int is more
     // specific than the other.
-    expect(_flatten(classA.type), classA.type);
-    expect(_flatten(classB.type), classB.type);
+    expect(_flatten(interfaceType(classA)), interfaceType(classA));
+    expect(_flatten(interfaceType(classB)), interfaceType(classB));
   }
 
   void test_visitAdjacentStrings() {
@@ -419,11 +418,11 @@
     // class A { ... this as B ... }
     // class B extends A {}
     ClassElement superclass = ElementFactory.classElement2("A");
-    InterfaceType superclassType = superclass.type;
+    InterfaceType superclassType = interfaceType(superclass);
     ClassElement subclass = ElementFactory.classElement("B", superclassType);
     Expression node = AstTestFactory.asExpression(
         AstTestFactory.thisExpression(), AstTestFactory.typeName(subclass));
-    expect(_analyze(node, superclassType), same(subclass.type));
+    expect(_analyze(node, superclassType), interfaceType(subclass));
     _listener.assertNoErrors();
   }
 
@@ -453,10 +452,9 @@
   void test_visitAwaitExpression_flattened() {
     // await e, where e has type Future<Future<int>>
     InterfaceType intType = _typeProvider.intType;
-    InterfaceType futureIntType =
-        _typeProvider.futureType.instantiate(<DartType>[intType]);
+    InterfaceType futureIntType = _typeProvider.futureType2(intType);
     InterfaceType futureFutureIntType =
-        _typeProvider.futureType.instantiate(<DartType>[futureIntType]);
+        _typeProvider.futureType2(futureIntType);
     Expression node = AstTestFactory.awaitExpression(
         _resolvedVariable(futureFutureIntType, 'e'));
     expect(_analyze(node), same(futureIntType));
@@ -466,8 +464,7 @@
   void test_visitAwaitExpression_simple() {
     // await e, where e has type Future<int>
     InterfaceType intType = _typeProvider.intType;
-    InterfaceType futureIntType =
-        _typeProvider.futureType.instantiate(<DartType>[intType]);
+    InterfaceType futureIntType = _typeProvider.futureType2(intType);
     Expression node =
         AstTestFactory.awaitExpression(_resolvedVariable(futureIntType, 'e'));
     expect(_analyze(node), same(intType));
@@ -552,7 +549,7 @@
     // }
     // (a as A) * 2.0
     ClassElementImpl classA = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
+    InterfaceType typeA = interfaceType(classA);
     MethodElement operator =
         ElementFactory.methodElement("*", typeA, [_typeProvider.doubleType]);
     classA.methods = <MethodElement>[operator];
@@ -649,21 +646,15 @@
     FunctionExpression node = _resolvedFunctionExpression(
         AstTestFactory.formalParameterList([]), body);
     DartType resultType = _analyze(node);
-    _assertFunctionType(
-        _typeProvider.futureType
-            .instantiate(<DartType>[_typeProvider.dynamicType]),
-        null,
-        null,
-        null,
-        resultType);
+    _assertFunctionType(_typeProvider.futureType2(_typeProvider.dynamicType),
+        null, null, null, resultType);
     _listener.assertNoErrors();
   }
 
   void test_visitFunctionExpression_async_expression_flatten() {
     // () async => e, where e has type Future<int>
     InterfaceType intType = _typeProvider.intType;
-    InterfaceType futureIntType =
-        _typeProvider.futureType.instantiate(<DartType>[intType]);
+    InterfaceType futureIntType = _typeProvider.futureType2(intType);
     Expression expression = _resolvedVariable(futureIntType, 'e');
     ExpressionFunctionBody body =
         AstTestFactory.expressionFunctionBody(expression);
@@ -671,23 +662,17 @@
     FunctionExpression node = _resolvedFunctionExpression(
         AstTestFactory.formalParameterList([]), body);
     DartType resultType = _analyze(node);
-    _assertFunctionType(
-        _typeProvider.futureType
-            .instantiate(<DartType>[_typeProvider.dynamicType]),
-        null,
-        null,
-        null,
-        resultType);
+    _assertFunctionType(_typeProvider.futureType2(_typeProvider.dynamicType),
+        null, null, null, resultType);
     _listener.assertNoErrors();
   }
 
   void test_visitFunctionExpression_async_expression_flatten_twice() {
     // () async => e, where e has type Future<Future<int>>
     InterfaceType intType = _typeProvider.intType;
-    InterfaceType futureIntType =
-        _typeProvider.futureType.instantiate(<DartType>[intType]);
+    InterfaceType futureIntType = _typeProvider.futureType2(intType);
     InterfaceType futureFutureIntType =
-        _typeProvider.futureType.instantiate(<DartType>[futureIntType]);
+        _typeProvider.futureType2(futureIntType);
     Expression expression = _resolvedVariable(futureFutureIntType, 'e');
     ExpressionFunctionBody body =
         AstTestFactory.expressionFunctionBody(expression);
@@ -695,13 +680,8 @@
     FunctionExpression node = _resolvedFunctionExpression(
         AstTestFactory.formalParameterList([]), body);
     DartType resultType = _analyze(node);
-    _assertFunctionType(
-        _typeProvider.futureType
-            .instantiate(<DartType>[_typeProvider.dynamicType]),
-        null,
-        null,
-        null,
-        resultType);
+    _assertFunctionType(_typeProvider.futureType2(_typeProvider.dynamicType),
+        null, null, null, resultType);
     _listener.assertNoErrors();
   }
 
@@ -932,7 +912,7 @@
             AstTestFactory.typeName(classElement),
             [AstTestFactory.identifier3(constructorName)]);
     node.staticElement = constructor;
-    expect(_analyze(node), same(classElement.type));
+    expect(_analyze(node), interfaceType(classElement));
     _listener.assertNoErrors();
   }
 
@@ -945,14 +925,15 @@
     elementC.constructors = <ConstructorElement>[constructor];
     TypeName typeName =
         AstTestFactory.typeName(elementC, [AstTestFactory.typeName(elementI)]);
-    typeName.type = elementC.type.instantiate(<DartType>[elementI.type]);
+    typeName.type =
+        interfaceType(elementC, typeArguments: [interfaceType(elementI)]);
     InstanceCreationExpression node =
         AstTestFactory.instanceCreationExpression2(null, typeName);
     node.staticElement = constructor;
-    InterfaceType interfaceType = _analyze(node) as InterfaceType;
-    List<DartType> typeArgs = interfaceType.typeArguments;
+    InterfaceType type = _analyze(node) as InterfaceType;
+    List<DartType> typeArgs = type.typeArguments;
     expect(typeArgs.length, 1);
-    expect(typeArgs[0], elementI.type);
+    expect(typeArgs[0], interfaceType(elementI));
     _listener.assertNoErrors();
   }
 
@@ -966,7 +947,7 @@
         AstTestFactory.instanceCreationExpression2(
             null, AstTestFactory.typeName(classElement));
     node.staticElement = constructor;
-    expect(_analyze(node), same(classElement.type));
+    expect(_analyze(node), interfaceType(classElement));
     _listener.assertNoErrors();
   }
 
@@ -998,9 +979,7 @@
     Expression node = AstTestFactory.listLiteral();
     DartType resultType = _analyze(node);
     _assertType2(
-        _typeProvider.listType
-            .instantiate(<DartType>[_typeProvider.dynamicType]),
-        resultType);
+        _typeProvider.listType2(_typeProvider.dynamicType), resultType);
     _listener.assertNoErrors();
   }
 
@@ -1008,9 +987,7 @@
     // [0]
     Expression node = AstTestFactory.listLiteral([_resolvedInteger(0)]);
     DartType resultType = _analyze(node);
-    _assertType2(
-        _typeProvider.listType.instantiate(<DartType>[_typeProvider.intType]),
-        resultType);
+    _assertType2(_typeProvider.listType2(_typeProvider.intType), resultType);
     _listener.assertNoErrors();
   }
 
@@ -1020,9 +997,7 @@
     Expression node = AstTestFactory.listLiteral([identifier]);
     DartType resultType = _analyze(node);
     _assertType2(
-        _typeProvider.listType
-            .instantiate(<DartType>[_typeProvider.dynamicType]),
-        resultType);
+        _typeProvider.listType2(_typeProvider.dynamicType), resultType);
     _listener.assertNoErrors();
   }
 
@@ -1032,9 +1007,7 @@
     Expression node = AstTestFactory.listLiteral(
         [_resolvedInteger(0), identifier, _resolvedInteger(1)]);
     DartType resultType = _analyze(node);
-    _assertType2(
-        _typeProvider.listType.instantiate(<DartType>[_typeProvider.intType]),
-        resultType);
+    _assertType2(_typeProvider.listType2(_typeProvider.intType), resultType);
     _listener.assertNoErrors();
   }
 
@@ -1043,8 +1016,8 @@
     Expression node = AstTestFactory.setOrMapLiteral(null, null);
     DartType resultType = _analyze(node);
     _assertType2(
-        _typeProvider.mapType.instantiate(
-            <DartType>[_typeProvider.dynamicType, _typeProvider.dynamicType]),
+        _typeProvider.mapType2(
+            _typeProvider.dynamicType, _typeProvider.dynamicType),
         resultType);
     _listener.assertNoErrors();
   }
@@ -1055,8 +1028,8 @@
         null, null, [AstTestFactory.mapLiteralEntry("k", _resolvedInteger(0))]);
     DartType resultType = _analyze(node);
     _assertType2(
-        _typeProvider.mapType.instantiate(
-            <DartType>[_typeProvider.dynamicType, _typeProvider.intType]),
+        _typeProvider.mapType2(
+            _typeProvider.dynamicType, _typeProvider.intType),
         resultType);
     _listener.assertNoErrors();
   }
@@ -1246,8 +1219,9 @@
 
   void test_visitSuperExpression() {
     // super
-    InterfaceType superType = ElementFactory.classElement2("A").type;
-    InterfaceType thisType = ElementFactory.classElement("B", superType).type;
+    InterfaceType superType = interfaceType(ElementFactory.classElement2("A"));
+    InterfaceType thisType =
+        interfaceType(ElementFactory.classElement("B", superType));
     Expression node = AstTestFactory.superExpression();
     expect(_analyze(node, thisType), same(thisType));
     _listener.assertNoErrors();
@@ -1260,9 +1234,8 @@
 
   void test_visitThisExpression() {
     // this
-    InterfaceType thisType =
-        ElementFactory.classElement("B", ElementFactory.classElement2("A").type)
-            .type;
+    InterfaceType thisType = interfaceType(ElementFactory.classElement(
+        "B", interfaceType(ElementFactory.classElement2("A"))));
     Expression node = AstTestFactory.thisExpression();
     expect(_analyze(node, thisType), same(thisType));
     _listener.assertNoErrors();
diff --git a/pkg/analyzer/test/generated/static_warning_code_test.dart b/pkg/analyzer/test/generated/static_warning_code_test.dart
index 0cfcdb3..beea4a3 100644
--- a/pkg/analyzer/test/generated/static_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_warning_code_test.dart
@@ -15,6 +15,9 @@
 
 @reflectiveTest
 class StaticWarningCodeTest extends DriverResolutionTest {
+  // TODO(brianwilkerson) Figure out what to do with the rest of these tests.
+  //  The names do not correspond to diagnostic codes, so it isn't clear what
+  //  they're testing.
   test_functionWithoutCall_direct() async {
     await assertNoErrorsInCode('''
 class A implements Function {
@@ -83,307 +86,6 @@
     ]);
   }
 
-  test_staticAccessToInstanceMember_method_invocation() async {
-    await assertErrorsInCode('''
-class A {
-  m() {}
-}
-main() {
-  A.m();
-}''', [
-      error(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, 34, 1),
-    ]);
-  }
-
-  test_staticAccessToInstanceMember_method_reference() async {
-    await assertErrorsInCode('''
-class A {
-  m() {}
-}
-main() {
-  A.m;
-}''', [
-      error(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, 34, 1),
-    ]);
-  }
-
-  test_staticAccessToInstanceMember_propertyAccess_field() async {
-    await assertErrorsInCode('''
-class A {
-  var f;
-}
-main() {
-  A.f;
-}''', [
-      error(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, 34, 1),
-    ]);
-  }
-
-  test_staticAccessToInstanceMember_propertyAccess_getter() async {
-    await assertErrorsInCode('''
-class A {
-  get f => 42;
-}
-main() {
-  A.f;
-}''', [
-      error(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, 40, 1),
-    ]);
-  }
-
-  test_staticAccessToInstanceMember_propertyAccess_setter() async {
-    await assertErrorsInCode('''
-class A {
-  set f(x) {}
-}
-main() {
-  A.f = 42;
-}''', [
-      error(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, 39, 1),
-    ]);
-  }
-
-  test_switchExpressionNotAssignable() async {
-    await assertErrorsInCode('''
-f(int p) {
-  switch (p) {
-    case 'a': break;
-  }
-}''', [
-      error(StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE, 21, 1),
-    ]);
-  }
-
-  test_typeAnnotationDeferredClass_asExpression() async {
-    newFile("/test/lib/lib1.dart", content: '''
-library lib1;
-class A {}''');
-    await assertErrorsInCode('''
-library root;
-import 'lib1.dart' deferred as a;
-f(var v) {
-  v as a.A;
-}''', [
-      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 66, 3),
-    ]);
-  }
-
-  test_typeAnnotationDeferredClass_catchClause() async {
-    newFile("/test/lib/lib1.dart", content: '''
-library lib1;
-class A {}''');
-    await assertErrorsInCode('''
-library root;
-import 'lib1.dart' deferred as a;
-f(var v) {
-  try {
-  } on a.A {
-  }
-}''', [
-      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 74, 3),
-    ]);
-  }
-
-  test_typeAnnotationDeferredClass_fieldFormalParameter() async {
-    newFile("/test/lib/lib1.dart", content: '''
-library lib1;
-class A {}''');
-    await assertErrorsInCode('''
-library root;
-import 'lib1.dart' deferred as a;
-class C {
-  var v;
-  C(a.A this.v);
-}''', [
-      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 71, 3),
-    ]);
-  }
-
-  test_typeAnnotationDeferredClass_functionDeclaration_returnType() async {
-    newFile("/test/lib/lib1.dart", content: '''
-library lib1;
-class A {}''');
-    await assertErrorsInCode('''
-library root;
-import 'lib1.dart' deferred as a;
-a.A f() { return null; }''', [
-      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 48, 3),
-    ]);
-  }
-
-  test_typeAnnotationDeferredClass_functionTypedFormalParameter_returnType() async {
-    newFile("/test/lib/lib1.dart", content: '''
-library lib1;
-class A {}''');
-    await assertErrorsInCode('''
-library root;
-import 'lib1.dart' deferred as a;
-f(a.A g()) {}''', [
-      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 50, 3),
-    ]);
-  }
-
-  test_typeAnnotationDeferredClass_isExpression() async {
-    newFile("/test/lib/lib1.dart", content: '''
-library lib1;
-class A {}''');
-    await assertErrorsInCode('''
-library root;
-import 'lib1.dart' deferred as a;
-f(var v) {
-  bool b = v is a.A;
-}''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 66, 1),
-      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 75, 3),
-    ]);
-  }
-
-  test_typeAnnotationDeferredClass_methodDeclaration_returnType() async {
-    newFile("/test/lib/lib1.dart", content: '''
-library lib1;
-class A {}''');
-    await assertErrorsInCode('''
-library root;
-import 'lib1.dart' deferred as a;
-class C {
-  a.A m() { return null; }
-}''', [
-      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 60, 3),
-    ]);
-  }
-
-  test_typeAnnotationDeferredClass_simpleFormalParameter() async {
-    newFile("/test/lib/lib1.dart", content: '''
-library lib1;
-class A {}''');
-    await assertErrorsInCode('''
-library root;
-import 'lib1.dart' deferred as a;
-f(a.A v) {}''', [
-      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 50, 3),
-    ]);
-  }
-
-  test_typeAnnotationDeferredClass_typeArgumentList() async {
-    newFile("/test/lib/lib1.dart", content: '''
-library lib1;
-class A {}''');
-    await assertErrorsInCode('''
-library root;
-import 'lib1.dart' deferred as a;
-class C<E> {}
-C<a.A> c;''', [
-      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 64, 3),
-    ]);
-  }
-
-  test_typeAnnotationDeferredClass_typeArgumentList2() async {
-    newFile("/test/lib/lib1.dart", content: '''
-library lib1;
-class A {}''');
-    await assertErrorsInCode('''
-library root;
-import 'lib1.dart' deferred as a;
-class C<E, F> {}
-C<a.A, a.A> c;''', [
-      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 67, 3),
-      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 72, 3),
-    ]);
-  }
-
-  test_typeAnnotationDeferredClass_typeParameter_bound() async {
-    newFile("/test/lib/lib1.dart", content: '''
-library lib1;
-class A {}''');
-    await assertErrorsInCode('''
-library root;
-import 'lib1.dart' deferred as a;
-class C<E extends a.A> {}''', [
-      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 66, 3),
-    ]);
-  }
-
-  test_typeAnnotationDeferredClass_variableDeclarationList() async {
-    newFile("/test/lib/lib1.dart", content: '''
-library lib1;
-class A {}''');
-    await assertErrorsInCode('''
-library root;
-import 'lib1.dart' deferred as a;
-a.A v;''', [
-      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 48, 3),
-    ]);
-  }
-
-  test_typeParameterReferencedByStatic_field() async {
-    await assertErrorsInCode('''
-class A<K> {
-  static K k;
-}''', [
-      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 22, 1),
-    ]);
-  }
-
-  test_typeParameterReferencedByStatic_getter() async {
-    await assertErrorsInCode('''
-class A<K> {
-  static K get k => null;
-}''', [
-      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 22, 1),
-    ]);
-  }
-
-  test_typeParameterReferencedByStatic_methodBodyReference() async {
-    await assertErrorsInCode('''
-class A<K> {
-  static m() {
-    K k;
-  }
-}''', [
-      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 32, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 34, 1),
-    ]);
-  }
-
-  test_typeParameterReferencedByStatic_methodParameter() async {
-    await assertErrorsInCode('''
-class A<K> {
-  static m(K k) {}
-}''', [
-      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 24, 1),
-    ]);
-  }
-
-  test_typeParameterReferencedByStatic_methodReturn() async {
-    await assertErrorsInCode('''
-class A<K> {
-  static K m() { return null; }
-}''', [
-      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 22, 1),
-    ]);
-  }
-
-  test_typeParameterReferencedByStatic_setter() async {
-    await assertErrorsInCode('''
-class A<K> {
-  static set s(K k) {}
-}''', [
-      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 28, 1),
-    ]);
-  }
-
-  test_typeParameterReferencedByStatic_simpleIdentifier() async {
-    await assertErrorsInCode('''
-class A<T> {
-  static foo() {
-    T;
-  }
-}
-''', [
-      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 34, 1),
-    ]);
-  }
-
   test_typePromotion_functionType_arg_InterToDyn() async {
     await assertNoErrorsInCode('''
 typedef FuncDyn(x);
@@ -397,318 +99,6 @@
 }''');
   }
 
-  test_typeTestNonType() async {
-    await assertErrorsInCode('''
-var A = 0;
-f(var p) {
-  if (p is A) {
-  }
-}''', [
-      error(StaticWarningCode.TYPE_TEST_WITH_NON_TYPE, 33, 1),
-    ]);
-  }
-
-  test_typeTestWithUndefinedName() async {
-    await assertErrorsInCode('''
-f(var p) {
-  if (p is A) {
-  }
-}''', [
-      error(StaticWarningCode.TYPE_TEST_WITH_UNDEFINED_NAME, 22, 1),
-    ]);
-  }
-
-  test_undefinedClass_instanceCreation() async {
-    await assertErrorsInCode('''
-f() { new C(); }
-''', [
-      error(CompileTimeErrorCode.UNDEFINED_CLASS, 10, 1),
-    ]);
-  }
-
-  test_undefinedClass_variableDeclaration() async {
-    await assertErrorsInCode('''
-f() { C c; }
-''', [
-      error(CompileTimeErrorCode.UNDEFINED_CLASS, 6, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 8, 1),
-    ]);
-  }
-
-  test_undefinedClassBoolean_variableDeclaration() async {
-    await assertErrorsInCode('''
-f() { boolean v; }
-''', [
-      error(StaticWarningCode.UNDEFINED_CLASS_BOOLEAN, 6, 7),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
-    ]);
-  }
-
-  @failingTest
-  test_undefinedIdentifier_commentReference() async {
-    await assertErrorsInCode('''
-/** [m] xxx [new B.c] */
-class A {
-}''', [
-      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 5, 1),
-      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 17, 1),
-    ]);
-  }
-
-  test_undefinedIdentifier_for() async {
-    await assertErrorsInCode('''
-f(var l) {
-  for (e in l) {
-  }
-}''', [
-      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 18, 1),
-    ]);
-  }
-
-  test_undefinedIdentifier_function() async {
-    await assertErrorsInCode('''
-int a() => b;
-''', [
-      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 11, 1),
-    ]);
-  }
-
-  test_undefinedIdentifier_importCore_withShow() async {
-    await assertErrorsInCode('''
-import 'dart:core' show List;
-main() {
-  List;
-  String;
-}''', [
-      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 49, 6),
-    ]);
-  }
-
-  test_undefinedIdentifier_initializer() async {
-    await assertErrorsInCode('''
-var a = b;
-''', [
-      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 8, 1),
-    ]);
-  }
-
-  test_undefinedIdentifier_methodInvocation() async {
-    await assertErrorsInCode('''
-f() { C.m(); }
-''', [
-      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 6, 1),
-    ]);
-  }
-
-  test_undefinedIdentifier_private_getter() async {
-    newFile("/test/lib/lib.dart", content: '''
-library lib;
-class A {
-  var _foo;
-}''');
-    await assertErrorsInCode('''
-import 'lib.dart';
-class B extends A {
-  test() {
-    var v = _foo;
-  }
-}''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 58, 1),
-      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 62, 4),
-    ]);
-  }
-
-  test_undefinedIdentifier_private_setter() async {
-    newFile("/test/lib/lib.dart", content: '''
-library lib;
-class A {
-  var _foo;
-}''');
-    await assertErrorsInCode('''
-import 'lib.dart';
-class B extends A {
-  test() {
-    _foo = 42;
-  }
-}''', [
-      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 54, 4),
-    ]);
-  }
-
-  test_undefinedIdentifierAwait_function() async {
-    await assertErrorsInCode('''
-void a() { await; }
-''', [
-      error(StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT, 11, 5),
-    ]);
-  }
-
-  test_undefinedNamedParameter() async {
-    await assertErrorsInCode('''
-f({a, b}) {}
-main() {
-  f(c: 1);
-}''', [
-      error(CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER, 26, 1),
-    ]);
-  }
-
-  test_undefinedStaticMethodOrGetter_getter() async {
-    await assertErrorsInCode('''
-class C {}
-f(var p) {
-  f(C.m);
-}''', [
-      error(StaticTypeWarningCode.UNDEFINED_GETTER, 28, 1),
-    ]);
-  }
-
-  test_undefinedStaticMethodOrGetter_getter_inSuperclass() async {
-    await assertErrorsInCode('''
-class S {
-  static int get g => 0;
-}
-class C extends S {}
-f(var p) {
-  f(C.g);
-}''', [
-      error(StaticTypeWarningCode.UNDEFINED_GETTER, 75, 1),
-    ]);
-  }
-
-  test_undefinedStaticMethodOrGetter_setter_inSuperclass() async {
-    await assertErrorsInCode('''
-class S {
-  static set s(int i) {}
-}
-class C extends S {}
-f(var p) {
-  f(C.s = 1);
-}''', [
-      error(StaticTypeWarningCode.UNDEFINED_SETTER, 75, 1),
-    ]);
-  }
-
-  test_useOfVoidResult_assignmentExpression_function() async {
-    await assertErrorsInCode('''
-void f() {}
-class A {
-  n() {
-    var a;
-    a = f();
-  }
-}''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 38, 1),
-      error(StaticWarningCode.USE_OF_VOID_RESULT, 49, 1),
-    ]);
-  }
-
-  test_useOfVoidResult_assignmentExpression_method() async {
-    await assertErrorsInCode('''
-class A {
-  void m() {}
-  n() {
-    var a;
-    a = m();
-  }
-}''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 40, 1),
-      error(StaticWarningCode.USE_OF_VOID_RESULT, 51, 1),
-    ]);
-  }
-
-  test_useOfVoidResult_await() async {
-    await assertNoErrorsInCode('''
-main() async {
-  void x;
-  await x;
-}''');
-  }
-
-  test_useOfVoidResult_inForLoop_error() async {
-    await assertErrorsInCode('''
-class A {
-  void m() {}
-  n() {
-    for(Object a = m();;) {}
-  }
-}''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 47, 1),
-      error(StaticWarningCode.USE_OF_VOID_RESULT, 51, 1),
-    ]);
-  }
-
-  test_useOfVoidResult_inForLoop_ok() async {
-    await assertNoErrorsInCode('''
-class A {
-  void m() {}
-  n() {
-    for(void a = m();;) {}
-  }
-}''');
-  }
-
-  test_useOfVoidResult_variableDeclaration_function_error() async {
-    await assertErrorsInCode('''
-void f() {}
-class A {
-  n() {
-    Object a = f();
-  }
-}''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 41, 1),
-      error(StaticWarningCode.USE_OF_VOID_RESULT, 45, 1),
-    ]);
-  }
-
-  test_useOfVoidResult_variableDeclaration_function_ok() async {
-    await assertNoErrorsInCode('''
-void f() {}
-class A {
-  n() {
-    void a = f();
-  }
-}''');
-  }
-
-  test_useOfVoidResult_variableDeclaration_method2() async {
-    await assertErrorsInCode('''
-class A {
-  void m() {}
-  n() {
-    Object a = m(), b = m();
-  }
-}''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 43, 1),
-      error(StaticWarningCode.USE_OF_VOID_RESULT, 47, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 52, 1),
-      error(StaticWarningCode.USE_OF_VOID_RESULT, 56, 1),
-    ]);
-  }
-
-  test_useOfVoidResult_variableDeclaration_method_error() async {
-    await assertErrorsInCode('''
-class A {
-  void m() {}
-  n() {
-    Object a = m();
-  }
-}''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 43, 1),
-      error(StaticWarningCode.USE_OF_VOID_RESULT, 47, 1),
-    ]);
-  }
-
-  test_useOfVoidResult_variableDeclaration_method_ok() async {
-    await assertNoErrorsInCode('''
-class A {
-  void m() {}
-  n() {
-    void a = m();
-  }
-}''');
-  }
-
   test_voidReturnForGetter() async {
     await assertNoErrorsInCode('''
 class S {
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index 4970fc2..bac33e6 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -7,6 +7,7 @@
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.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/analysis/driver.dart';
 import 'package:analyzer/src/dart/element/element.dart';
@@ -1133,7 +1134,6 @@
   AsserterBuilder<DartType, DartType> _isType;
 
   AsserterBuilder<Element, DartType> _hasElement;
-  AsserterBuilder<DartType, DartType> _hasElementOf;
 
   @override
   Future<TestAnalysisResult> computeAnalysisResult(Source source) async {
@@ -1152,15 +1152,14 @@
       _isListOf = _assertions.isListOf;
       _isMapOf = _assertions.isMapOf;
       _isFunction2Of = _assertions.isFunction2Of;
-      _hasElementOf = _assertions.hasElementOf;
-      _isFutureOf = _isInstantiationOf(_hasElementOf(typeProvider.futureType));
+      _isFutureOf = _isInstantiationOf(_hasElement(typeProvider.futureElement));
       _isFutureOrOf =
-          _isInstantiationOf(_hasElementOf(typeProvider.futureOrType));
+          _isInstantiationOf(_hasElement(typeProvider.futureOrElement));
       _isFutureOfDynamic = _isFutureOf([_isDynamic]);
       _isFutureOfInt = _isFutureOf([_isInt]);
       _isFutureOfNull = _isFutureOf([_isNull]);
       _isFutureOrOfInt = _isFutureOrOf([_isInt]);
-      _isStreamOf = _isInstantiationOf(_hasElementOf(typeProvider.streamType));
+      _isStreamOf = _isInstantiationOf(_hasElement(typeProvider.streamElement));
     }
     return result;
   }
@@ -1821,8 +1820,10 @@
     ClassElement elementB = AstFinder.getClass(unit, "B").declaredElement;
     ClassElement elementA = AstFinder.getClass(unit, "A").declaredElement;
     expect(exp.constructorName.type.type.element, elementB);
-    _isInstantiationOf(_hasElement(elementB))(
-        [_isType(elementA.typeParameters[0].type)])(exp.staticType);
+    _isInstantiationOf(_hasElement(elementB))([
+      _isType(elementA.typeParameters[0]
+          .instantiate(nullabilitySuffix: NullabilitySuffix.star))
+    ])(exp.staticType);
   }
 
   test_fieldDeclaration_propagation() async {
@@ -4354,8 +4355,7 @@
     expect(ft.toString(), 'List<int> Function(String)');
 
     SimpleIdentifier x = findIdentifier('x');
-    expect(x.staticType,
-        typeProvider.listType.instantiate([typeProvider.intType]));
+    expect(x.staticType, typeProvider.listType2(typeProvider.intType));
   }
 
   test_genericMethod_functionExpressionInvocation_explicit() async {
diff --git a/pkg/analyzer/test/generated/test_analysis_context.dart b/pkg/analyzer/test/generated/test_analysis_context.dart
index 3c6918f..29f75ef 100644
--- a/pkg/analyzer/test/generated/test_analysis_context.dart
+++ b/pkg/analyzer/test/generated/test_analysis_context.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/analysis/features.dart';
-import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -15,7 +15,7 @@
   final SourceFactory sourceFactory = _MockSourceFactory();
 
   AnalysisOptions _analysisOptions;
-  TypeProvider _typeProvider;
+  TypeProviderImpl _typeProvider;
   TypeSystem _typeSystem;
 
   TestAnalysisContext({FeatureSet featureSet}) {
@@ -33,6 +33,11 @@
       sdkElements.coreLibrary,
       sdkElements.asyncLibrary,
     );
+
+    if (_analysisOptions.contextFeatures.isEnabled(Feature.non_nullable)) {
+      _typeProvider = _typeProvider.withNullability(NullabilitySuffix.none);
+    }
+
     _typeSystem = Dart2TypeSystem(typeProvider);
   }
 
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index 6e6cd92..19384d1 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -8,19 +8,18 @@
 import 'package:analyzer/dart/ast/standard_ast_factory.dart' show astFactory;
 import 'package:analyzer/dart/ast/token.dart' show Keyword;
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/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/type.dart';
-import 'package:analyzer/src/dart/element/type_provider.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/source.dart'
     show NonExistingSource, UriKind;
 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:meta/meta.dart';
 import 'package:path/path.dart' show toUri;
@@ -57,10 +56,6 @@
 
   InterfaceType get intType => typeProvider.intType;
 
-  InterfaceType get iterableType => typeProvider.iterableType;
-
-  InterfaceType get listType => typeProvider.listType;
-
   DartType get neverType => typeProvider.neverType;
 
   DartType get nullType => typeProvider.nullType;
@@ -71,18 +66,184 @@
 
   InterfaceType get stringType => typeProvider.stringType;
 
+  FeatureSet get testFeatureSet {
+    return FeatureSet.forTesting();
+  }
+
   DartType get voidType => VoidTypeImpl.instance;
 
+  DartType futureOrType(DartType T) {
+    var futureOrElement = typeProvider.futureOrElement;
+    return _interfaceType(futureOrElement, typeArguments: [T]);
+  }
+
+  DartType futureType(DartType T) {
+    var futureElement = typeProvider.futureElement;
+    return _interfaceType(futureElement, typeArguments: [T]);
+  }
+
+  DartType iterableType(DartType T) {
+    var iterableElement = typeProvider.iterableElement;
+    return _interfaceType(iterableElement, typeArguments: [T]);
+  }
+
+  DartType listType(DartType T) {
+    var listElement = typeProvider.listElement;
+    return _interfaceType(listElement, typeArguments: [T]);
+  }
+
   void setUp() {
-    typeProvider = new TestTypeProvider();
-    typeSystem = new Dart2TypeSystem(typeProvider);
+    var analysisContext = TestAnalysisContext(
+      featureSet: testFeatureSet,
+    );
+    typeProvider = analysisContext.typeProvider;
+    typeSystem = analysisContext.typeSystem;
+  }
+
+  ClassElementImpl _class({
+    @required String name,
+    bool isAbstract = false,
+    InterfaceType superType,
+    List<TypeParameterElement> typeParameters = const [],
+    List<InterfaceType> interfaces = const [],
+    List<InterfaceType> mixins = const [],
+    List<MethodElement> methods = const [],
+  }) {
+    var element = ClassElementImpl(name, 0);
+    element.typeParameters = typeParameters;
+    element.supertype = superType ?? objectType;
+    element.interfaces = interfaces;
+    element.mixins = mixins;
+    element.methods = methods;
+    return element;
+  }
+
+  /**
+   * Creates a function type with the given parameter and return types.
+   *
+   * The return type defaults to `void` if omitted.
+   */
+  FunctionType _functionType({
+    List<TypeParameterElement> typeFormals,
+    List<DartType> required,
+    List<DartType> optional,
+    Map<String, DartType> named,
+    DartType returns,
+    NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
+  }) {
+    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 ?? voidType,
+      typeFormals ?? const <TypeParameterElement>[],
+      parameters,
+      nullabilitySuffix: nullabilitySuffix,
+    );
+  }
+
+  InterfaceType _interfaceType(
+    ClassElement element, {
+    List<DartType> typeArguments = const [],
+    NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
+  }) {
+    return InterfaceTypeImpl.explicit(
+      element,
+      typeArguments,
+      nullabilitySuffix: nullabilitySuffix,
+    );
+  }
+
+  MethodElementImpl _method(
+    String name,
+    DartType returnType, {
+    List<TypeParameterElement> typeFormals = const [],
+    List<ParameterElement> parameters = const [],
+  }) {
+    var element = MethodElementImpl(name, 0)
+      ..parameters = parameters
+      ..returnType = returnType
+      ..typeParameters = typeFormals;
+    element.type = _typeOfExecutableElement(element);
+    return element;
+  }
+
+  ParameterElement _requiredParameter(String name, DartType type) {
+    var parameter = ParameterElementImpl(name, 0);
+    parameter.parameterKind = ParameterKind.REQUIRED;
+    parameter.type = type;
+    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;
+    return element;
+  }
+
+  TypeParameterTypeImpl _typeParameterType(
+    TypeParameterElement element, {
+    NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
+  }) {
+    return TypeParameterTypeImpl(
+      element,
+      nullabilitySuffix: nullabilitySuffix,
+    );
   }
 }
 
 @reflectiveTest
 class AssignabilityTest extends AbstractTypeSystemTest {
   void test_isAssignableTo_bottom_isBottom() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    var A = _class(name: 'A');
     List<DartType> interassignable = <DartType>[
       dynamicType,
       objectType,
@@ -90,53 +251,59 @@
       doubleType,
       numType,
       stringType,
-      interfaceType,
-      bottomType
+      _interfaceType(A),
+      bottomType,
     ];
 
     _checkGroups(bottomType, interassignable: interassignable);
   }
 
   void test_isAssignableTo_call_method() {
-    ClassElementImpl classBottom = ElementFactory.classElement2("B");
-    MethodElement methodBottom =
-        ElementFactory.methodElement("call", objectType, <DartType>[intType]);
-    classBottom.methods = <MethodElement>[methodBottom];
+    var B = _class(
+      name: 'B',
+      methods: [
+        _method('call', objectType, parameters: [
+          _requiredParameter('_', intType),
+        ]),
+      ],
+    );
 
-    DartType top =
-        TypeBuilder.function(required: <DartType>[intType], result: objectType);
-    InterfaceType bottom = classBottom.type;
-
-    _checkIsStrictAssignableTo(bottom, top);
+    _checkIsStrictAssignableTo(
+      _interfaceType(B),
+      _functionType(required: [intType], returns: objectType),
+    );
   }
 
   void test_isAssignableTo_classes() {
-    ClassElement classTop = ElementFactory.classElement2("A");
-    ClassElement classLeft = ElementFactory.classElement("B", classTop.type);
-    ClassElement classRight = ElementFactory.classElement("C", classTop.type);
-    ClassElement classBottom = ElementFactory.classElement("D", classLeft.type)
-      ..interfaces = <InterfaceType>[classRight.type];
-    InterfaceType top = classTop.type;
-    InterfaceType left = classLeft.type;
-    InterfaceType right = classRight.type;
-    InterfaceType bottom = classBottom.type;
+    var classTop = _class(name: 'A');
+    var classLeft = _class(name: 'B', superType: _interfaceType(classTop));
+    var classRight = _class(name: 'C', superType: _interfaceType(classTop));
+    var classBottom = _class(
+      name: 'D',
+      superType: _interfaceType(classLeft),
+      interfaces: [_interfaceType(classRight)],
+    );
+    var top = _interfaceType(classTop);
+    var left = _interfaceType(classLeft);
+    var right = _interfaceType(classRight);
+    var bottom = _interfaceType(classBottom);
 
     _checkLattice(top, left, right, bottom);
   }
 
   void test_isAssignableTo_double() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    var A = _class(name: 'A');
     List<DartType> interassignable = <DartType>[
       dynamicType,
       objectType,
       doubleType,
       numType,
-      bottomType
+      bottomType,
     ];
     List<DartType> unrelated = <DartType>[
       intType,
       stringType,
-      interfaceType,
+      _interfaceType(A),
     ];
 
     _checkGroups(doubleType,
@@ -144,7 +311,7 @@
   }
 
   void test_isAssignableTo_dynamic_isTop() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    var A = _class(name: 'A');
     List<DartType> interassignable = <DartType>[
       dynamicType,
       objectType,
@@ -152,42 +319,49 @@
       doubleType,
       numType,
       stringType,
-      interfaceType,
-      bottomType
+      _interfaceType(A),
+      bottomType,
     ];
     _checkGroups(dynamicType, interassignable: interassignable);
   }
 
   void test_isAssignableTo_generics() {
-    ClassElementImpl LClass = ElementFactory.classElement2('L', ["T"]);
-    InterfaceType LType = LClass.type;
-    ClassElementImpl MClass = ElementFactory.classElement2('M', ["T"]);
-    DartType typeParam = MClass.typeParameters[0].type;
-    InterfaceType superType = LType.instantiate(<DartType>[typeParam]);
-    MClass.interfaces = <InterfaceType>[superType];
-    InterfaceType MType = MClass.type;
+    var LT = _typeParameter('T');
+    var L = _class(name: 'L', typeParameters: [LT]);
 
-    InterfaceType top = LType.instantiate(<DartType>[dynamicType]);
-    InterfaceType left = MType.instantiate(<DartType>[dynamicType]);
-    InterfaceType right = LType.instantiate(<DartType>[intType]);
-    InterfaceType bottom = MType.instantiate(<DartType>[intType]);
+    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]);
 
     _checkCrossLattice(top, left, right, bottom);
   }
 
   void test_isAssignableTo_int() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    var A = _class(name: 'A');
     List<DartType> interassignable = <DartType>[
       dynamicType,
       objectType,
       intType,
       numType,
-      bottomType
+      bottomType,
     ];
     List<DartType> unrelated = <DartType>[
       doubleType,
       stringType,
-      interfaceType,
+      _interfaceType(A),
     ];
 
     _checkGroups(intType,
@@ -195,36 +369,36 @@
   }
 
   void test_isAssignableTo_named_optional() {
-    DartType r =
-        TypeBuilder.function(required: <DartType>[intType], result: intType);
-    DartType o = TypeBuilder.function(
-        required: <DartType>[], optional: <DartType>[intType], result: intType);
-    DartType n = TypeBuilder.function(
-        required: <DartType>[],
-        named: <String, DartType>{'x': intType},
-        result: intType);
-    DartType rr = TypeBuilder.function(
-        required: <DartType>[intType, intType], result: intType);
-    DartType ro = TypeBuilder.function(
-        required: <DartType>[intType],
-        optional: <DartType>[intType],
-        result: intType);
-    DartType rn = TypeBuilder.function(
-        required: <DartType>[intType],
-        named: <String, DartType>{'x': intType},
-        result: intType);
-    DartType oo = TypeBuilder.function(
-        required: <DartType>[],
-        optional: <DartType>[intType, intType],
-        result: intType);
-    DartType nn = TypeBuilder.function(
-        required: <DartType>[],
-        named: <String, DartType>{'x': intType, 'y': intType},
-        result: intType);
-    DartType nnn = TypeBuilder.function(
-        required: <DartType>[],
-        named: <String, DartType>{'x': intType, 'y': intType, 'z': intType},
-        result: intType);
+    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,
         interassignable: [r, o, ro, rn, oo], unrelated: [n, rr, nn, nnn]);
@@ -245,18 +419,18 @@
   }
 
   void test_isAssignableTo_num() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    var A = _class(name: 'A');
     List<DartType> interassignable = <DartType>[
       dynamicType,
       objectType,
       numType,
       intType,
       doubleType,
-      bottomType
+      bottomType,
     ];
     List<DartType> unrelated = <DartType>[
       stringType,
-      interfaceType,
+      _interfaceType(A),
     ];
 
     _checkGroups(numType,
@@ -264,23 +438,17 @@
   }
 
   void test_isAssignableTo_simple_function() {
-    FunctionType top =
-        TypeBuilder.function(required: <DartType>[intType], result: objectType);
-    FunctionType left =
-        TypeBuilder.function(required: <DartType>[intType], result: intType);
-    FunctionType right = TypeBuilder.function(
-        required: <DartType>[objectType], result: objectType);
-    FunctionType bottom =
-        TypeBuilder.function(required: <DartType>[objectType], result: intType);
+    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);
 
     _checkCrossLattice(top, left, right, bottom);
   }
 
   void test_isAssignableTo_void_functions() {
-    FunctionType top =
-        TypeBuilder.function(required: <DartType>[intType], result: voidType);
-    FunctionType bottom =
-        TypeBuilder.function(required: <DartType>[objectType], result: intType);
+    var top = _functionType(required: [intType], returns: voidType);
+    var bottom = _functionType(required: [objectType], returns: intType);
 
     _checkEquivalent(bottom, top);
   }
@@ -348,48 +516,10 @@
 /**
  * Base class for testing LUB and GLB in spec and strong mode.
  */
-abstract class BoundTestBase {
-  TypeProvider typeProvider;
-  Dart2TypeSystem typeSystem;
-  FunctionType simpleFunctionType;
-
-  DartType get bottomType => typeProvider.bottomType;
-
-  InterfaceType get doubleType => typeProvider.doubleType;
-
-  DartType get dynamicType => typeProvider.dynamicType;
-
-  InterfaceType get functionType => typeProvider.functionType;
-
-  InterfaceType get futureOrType => typeProvider.futureOrType;
-
-  InterfaceType get intType => typeProvider.intType;
-
-  InterfaceType get iterableType => typeProvider.iterableType;
-
-  InterfaceType get listType => typeProvider.listType;
-
-  InterfaceType get nullType => typeProvider.nullType;
-
-  InterfaceType get numType => typeProvider.numType;
-
-  InterfaceType get objectType => typeProvider.objectType;
-
-  InterfaceType get stringType => typeProvider.stringType;
-
-  DartType get voidType => VoidTypeImpl.instance;
-
-  void setUp() {
-    var analysisContext = TestAnalysisContext();
-    typeProvider = analysisContext.typeProvider;
-    var simpleFunctionElement =
-        ElementFactory.genericTypeAliasElement('A', returnType: voidType);
-    simpleFunctionType = simpleFunctionElement.type;
-  }
-
+abstract class BoundTestBase extends AbstractTypeSystemTest {
   void _checkGreatestLowerBound(
       DartType type1, DartType type2, DartType expectedResult) {
-    DartType glb = typeSystem.getGreatestLowerBound(type1, type2);
+    var glb = typeSystem.getGreatestLowerBound(type1, type2);
     expect(glb, expectedResult);
     // Check that the result is a lower bound.
     expect(typeSystem.isSubtypeOf(glb, type1), true);
@@ -411,7 +541,7 @@
 
   void _checkLeastUpperBound(
       DartType type1, DartType type2, DartType expectedResult) {
-    DartType lub = typeSystem.getLeastUpperBound(type1, type2);
+    var lub = typeSystem.getLeastUpperBound(type1, type2);
     expect(lub, expectedResult);
     // Check that the result is an upper bound.
     expect(typeSystem.isSubtypeOf(type1, lub), true);
@@ -431,151 +561,68 @@
       expect(lub, expectedResult);
     }
   }
-
-  /**
-   * Creates a function type with the given parameter and return types.
-   *
-   * The return type defaults to `void` if omitted.
-   */
-  FunctionType _functionType({
-    List<TypeParameterElement> typeFormals,
-    List<DartType> required,
-    List<DartType> optional,
-    Map<String, DartType> named,
-    DartType returns,
-  }) {
-    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 ?? voidType,
-      typeFormals ?? const <TypeParameterElement>[],
-      parameters,
-    );
-  }
-
-  TypeParameterElementImpl _typeParameterElement(String name,
-      {DartType bound}) {
-    var element = TypeParameterElementImpl.synthetic(name);
-    element.bound = bound ?? typeProvider.objectType;
-    return element;
-  }
 }
 
 @reflectiveTest
-class ConstraintMatchingTest {
-  TypeProvider typeProvider;
-  TypeSystem typeSystem;
+class ConstraintMatchingTest extends AbstractTypeSystemTest {
   TypeParameterType T;
 
-  DartType get dynamicType => DynamicTypeImpl.instance;
-
-  InterfaceType get functionType => typeProvider.functionType;
-
-  InterfaceType get intType => typeProvider.intType;
-
-  InterfaceType get nullType => typeProvider.nullType;
-
-  InterfaceType get objectType => typeProvider.objectType;
-
-  InterfaceType get stringType => typeProvider.stringType;
-
-  DartType get voidType => VoidTypeImpl.instance;
-
-  DartType fn(DartType paramType, DartType returnType) =>
-      new FunctionElementImpl.synthetic([
-        new ParameterElementImpl.synthetic(
-            'value', paramType, ParameterKind.REQUIRED)
-      ], returnType)
-          .type;
-
-  DartType future(DartType T) => typeProvider.futureType.instantiate([T]);
-
-  DartType futureOr(DartType T) => typeProvider.futureOrType.instantiate([T]);
-
-  DartType iterable(DartType T) => typeProvider.iterableType.instantiate([T]);
-
-  DartType list(DartType T) => typeProvider.listType.instantiate([T]);
-
   void setUp() {
-    var analysisContext = TestAnalysisContext();
-    typeProvider = analysisContext.typeProvider;
-    typeSystem = analysisContext.typeSystem;
-    T = _newTypeParameter('T');
+    super.setUp();
+    T = _typeParameterType(
+      _typeParameter('T'),
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
   }
 
   void test_function_coreFunction() {
-    _checkOrdinarySubtypeMatch(fn(intType, stringType), functionType, [T],
-        covariant: true);
+    _checkOrdinarySubtypeMatch(
+      _functionType(required: [intType], returns: stringType),
+      functionType,
+      [T],
+      covariant: true,
+    );
   }
 
   void test_function_parameter_types() {
     _checkIsSubtypeMatchOf(
-        fn(T, intType), fn(stringType, intType), [T], ['String <: T'],
-        covariant: true);
+      _functionType(required: [T], returns: intType),
+      _functionType(required: [stringType], returns: intType),
+      [T],
+      ['String <: T'],
+      covariant: true,
+    );
   }
 
   void test_function_return_types() {
     _checkIsSubtypeMatchOf(
-        fn(intType, T), fn(intType, stringType), [T], ['T <: String'],
-        covariant: true);
+      _functionType(required: [intType], returns: T),
+      _functionType(required: [intType], returns: stringType),
+      [T],
+      ['T <: String'],
+      covariant: true,
+    );
   }
 
   void test_futureOr_futureOr() {
     _checkIsSubtypeMatchOf(
-        futureOr(T), futureOr(stringType), [T], ['T <: String'],
+        futureOrType(T), futureOrType(stringType), [T], ['T <: String'],
         covariant: true);
   }
 
   void test_futureOr_x_fail_future_branch() {
     // FutureOr<List<T>> <: List<String> can't be satisfied because
     // Future<List<T>> <: List<String> can't be satisfied
-    _checkIsNotSubtypeMatchOf(futureOr(list(T)), list(stringType), [T],
+    _checkIsNotSubtypeMatchOf(
+        futureOrType(listType(T)), listType(stringType), [T],
         covariant: true);
   }
 
   void test_futureOr_x_fail_nonFuture_branch() {
     // FutureOr<List<T>> <: Future<List<String>> can't be satisfied because
     // List<T> <: Future<List<String>> can't be satisfied
-    _checkIsNotSubtypeMatchOf(futureOr(list(T)), future(list(stringType)), [T],
+    _checkIsNotSubtypeMatchOf(
+        futureOrType(listType(T)), futureType(listType(stringType)), [T],
         covariant: true);
   }
 
@@ -583,7 +630,7 @@
     // FutureOr<T> <: Future<T> can be satisfied by T=Null.  At this point in
     // the type inference algorithm all we figure out is that T must be a
     // subtype of both String and Future<String>.
-    _checkIsSubtypeMatchOf(futureOr(T), future(stringType), [T],
+    _checkIsSubtypeMatchOf(futureOrType(T), futureType(stringType), [T],
         ['T <: String', 'T <: Future<String>'],
         covariant: true);
   }
@@ -593,14 +640,18 @@
     _checkIsSubtypeMatchOf(nullType, T, [T], ['Null <: T'], covariant: false);
     // For any other type X, Null <: X is satisfied without the need for any
     // constraints.
-    _checkOrdinarySubtypeMatch(nullType, list(T), [T], covariant: false);
+    _checkOrdinarySubtypeMatch(nullType, listType(T), [T], covariant: false);
     _checkOrdinarySubtypeMatch(nullType, stringType, [T], covariant: false);
     _checkOrdinarySubtypeMatch(nullType, voidType, [T], covariant: false);
     _checkOrdinarySubtypeMatch(nullType, dynamicType, [T], covariant: false);
     _checkOrdinarySubtypeMatch(nullType, objectType, [T], covariant: false);
     _checkOrdinarySubtypeMatch(nullType, nullType, [T], covariant: false);
-    _checkOrdinarySubtypeMatch(nullType, fn(intType, stringType), [T],
-        covariant: false);
+    _checkOrdinarySubtypeMatch(
+      nullType,
+      _functionType(required: [intType], returns: stringType),
+      [T],
+      covariant: false,
+    );
   }
 
   void test_param_on_lhs_contravariant_direct() {
@@ -613,8 +664,11 @@
     //
     // In other words, List<S> <: List<T> is satisfied provided that
     // S <: T.
-    var S = _newTypeParameter('S');
-    _checkIsSubtypeMatchOf(list(S), list(T), [T], ['S <: T'], covariant: false);
+    var S = _typeParameterType(
+      _typeParameter('S'),
+    );
+    _checkIsSubtypeMatchOf(listType(S), listType(T), [T], ['S <: T'],
+        covariant: false);
   }
 
   void test_param_on_lhs_contravariant_via_bound() {
@@ -625,8 +679,14 @@
     //
     // In other words, S <: List<T> is satisfied provided that
     // bound(S) <: List<T>.
-    var S = _newTypeParameter('S', list(stringType));
-    _checkIsSubtypeMatchOf(S, list(T), [T], ['String <: T'], covariant: false);
+    var S = _typeParameterType(
+      _typeParameter(
+        'S',
+        bound: listType(stringType),
+      ),
+    );
+    _checkIsSubtypeMatchOf(S, listType(T), [T], ['String <: T'],
+        covariant: false);
   }
 
   void test_param_on_lhs_covariant() {
@@ -652,7 +712,9 @@
     //
     // In other words, T <: S can be satisfied trivially by the constraint
     // T <: S.
-    var S = _newTypeParameter('S');
+    var S = _typeParameterType(
+      _typeParameter('S'),
+    );
     _checkIsSubtypeMatchOf(T, S, [T], ['T <: S'], covariant: true);
   }
 
@@ -666,17 +728,20 @@
     //
     // In other words, no match can be found for List<T> <: S because regardless
     // of T, we can't guarantee that List<T> <: S for all S.
-    var S = _newTypeParameter('S');
-    _checkIsNotSubtypeMatchOf(list(T), S, [T], covariant: true);
+    var S = _typeParameterType(
+      _typeParameter('S'),
+    );
+    _checkIsNotSubtypeMatchOf(listType(T), S, [T], covariant: true);
   }
 
   void test_related_interface_types_failure() {
-    _checkIsNotSubtypeMatchOf(iterable(T), list(stringType), [T],
+    _checkIsNotSubtypeMatchOf(iterableType(T), listType(stringType), [T],
         covariant: true);
   }
 
   void test_related_interface_types_success() {
-    _checkIsSubtypeMatchOf(list(T), iterable(stringType), [T], ['T <: String'],
+    _checkIsSubtypeMatchOf(
+        listType(T), iterableType(stringType), [T], ['T <: String'],
         covariant: true);
   }
 
@@ -686,14 +751,18 @@
         covariant: true);
     // For any other type X, X <: dynamic is satisfied without the need for any
     // constraints.
-    _checkOrdinarySubtypeMatch(list(T), dynamicType, [T], covariant: true);
+    _checkOrdinarySubtypeMatch(listType(T), dynamicType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(stringType, dynamicType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(voidType, dynamicType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(dynamicType, dynamicType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(objectType, dynamicType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(nullType, dynamicType, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(fn(intType, stringType), dynamicType, [T],
-        covariant: true);
+    _checkOrdinarySubtypeMatch(
+      _functionType(required: [intType], returns: stringType),
+      dynamicType,
+      [T],
+      covariant: true,
+    );
   }
 
   void test_rhs_object() {
@@ -702,14 +771,18 @@
         covariant: true);
     // For any other type X, X <: Object is satisfied without the need for any
     // constraints.
-    _checkOrdinarySubtypeMatch(list(T), objectType, [T], covariant: true);
+    _checkOrdinarySubtypeMatch(listType(T), objectType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(stringType, objectType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(voidType, objectType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(dynamicType, objectType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(objectType, objectType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(nullType, objectType, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(fn(intType, stringType), objectType, [T],
-        covariant: true);
+    _checkOrdinarySubtypeMatch(
+      _functionType(required: [intType], returns: stringType),
+      objectType,
+      [T],
+      covariant: true,
+    );
   }
 
   void test_rhs_void() {
@@ -717,25 +790,30 @@
     _checkIsSubtypeMatchOf(T, voidType, [T], ['T <: void'], covariant: true);
     // For any other type X, X <: void is satisfied without the need for any
     // constraints.
-    _checkOrdinarySubtypeMatch(list(T), voidType, [T], covariant: true);
+    _checkOrdinarySubtypeMatch(listType(T), voidType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(stringType, voidType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(voidType, voidType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(dynamicType, voidType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(objectType, voidType, [T], covariant: true);
     _checkOrdinarySubtypeMatch(nullType, voidType, [T], covariant: true);
-    _checkOrdinarySubtypeMatch(fn(intType, stringType), voidType, [T],
-        covariant: true);
+    _checkOrdinarySubtypeMatch(
+      _functionType(required: [intType], returns: stringType),
+      voidType,
+      [T],
+      covariant: true,
+    );
   }
 
   void test_same_interface_types() {
-    _checkIsSubtypeMatchOf(list(T), list(stringType), [T], ['T <: String'],
+    _checkIsSubtypeMatchOf(
+        listType(T), listType(stringType), [T], ['T <: String'],
         covariant: true);
   }
 
   void test_x_futureOr_fail_both_branches() {
     // List<T> <: FutureOr<String> can't be satisfied because neither
     // List<T> <: Future<String> nor List<T> <: int can be satisfied
-    _checkIsNotSubtypeMatchOf(list(T), futureOr(stringType), [T],
+    _checkIsNotSubtypeMatchOf(listType(T), futureOrType(stringType), [T],
         covariant: true);
   }
 
@@ -747,7 +825,7 @@
     // constraint Future<String> <: T.  We keep the constraint based on trying
     // to match Future<String> <: Future<T>, so String <: T.
     _checkIsSubtypeMatchOf(
-        future(stringType), futureOr(T), [T], ['String <: T'],
+        futureType(stringType), futureOrType(T), [T], ['String <: T'],
         covariant: false);
   }
 
@@ -758,7 +836,7 @@
     // T <: Object, whereas trying to match Future<T> <: Object generates no
     // constraints, so we keep the constraint T <: Object.
     _checkIsSubtypeMatchOf(
-        future(T), futureOr(objectType), [T], ['T <: Object'],
+        futureType(T), futureOrType(objectType), [T], ['T <: Object'],
         covariant: true);
   }
 
@@ -768,7 +846,7 @@
     // Trying to match Null <: FutureOr<T> generates no constraints, whereas
     // trying to match Null <: T generates the constraint Null <: T,
     // so we keep the constraint Null <: T.
-    _checkIsSubtypeMatchOf(nullType, futureOr(T), [T], ['Null <: T'],
+    _checkIsSubtypeMatchOf(nullType, futureOrType(T), [T], ['Null <: T'],
         covariant: false);
   }
 
@@ -776,7 +854,8 @@
     // Future<String> <: FutureOr<Object> is satisfied because both
     // Future<String> <: Future<Object> and Future<String> <: Object.
     // No constraints are recorded.
-    _checkIsSubtypeMatchOf(future(stringType), futureOr(objectType), [T], [],
+    _checkIsSubtypeMatchOf(
+        futureType(stringType), futureOrType(objectType), [T], [],
         covariant: true);
   }
 
@@ -784,7 +863,7 @@
     // Future<T> <: FutureOr<String> can be satisfied because
     // Future<T> <: Future<String> can be satisfied
     _checkIsSubtypeMatchOf(
-        future(T), futureOr(stringType), [T], ['T <: String'],
+        futureType(T), futureOrType(stringType), [T], ['T <: String'],
         covariant: true);
   }
 
@@ -792,7 +871,7 @@
     // List<T> <: FutureOr<List<String>> can be satisfied because
     // List<T> <: List<String> can be satisfied
     _checkIsSubtypeMatchOf(
-        list(T), futureOr(list(stringType)), [T], ['T <: String'],
+        listType(T), futureOrType(listType(stringType)), [T], ['T <: String'],
         covariant: true);
   }
 
@@ -839,66 +918,68 @@
       _checkIsNotSubtypeMatchOf(t1, t2, typeFormals);
     }
   }
-
-  TypeParameterType _newTypeParameter(String name, [DartType bound]) {
-    var element = new TypeParameterElementImpl(name, 0);
-    if (bound != null) {
-      element.bound = bound;
-    }
-    return new TypeParameterTypeImpl(element);
-  }
 }
 
 @reflectiveTest
 class GenericFunctionInferenceTest extends AbstractTypeSystemTest {
   void test_boundedByAnotherTypeParameter() {
     // <TFrom, TTo extends Iterable<TFrom>>(TFrom) -> TTo
-    var tFrom = TypeBuilder.variable('TFrom');
+    var tFrom = _typeParameter('TFrom');
     var tTo =
-        TypeBuilder.variable('TTo', bound: iterableType.instantiate([tFrom]));
-    var cast = TypeBuilder.function(
-        types: [tFrom, tTo], required: [tFrom], result: tTo);
-    expect(_inferCall(cast, [stringType]), [
-      stringType,
-      iterableType.instantiate([stringType])
-    ]);
+        _typeParameter('TTo', bound: iterableType(_typeParameterType(tFrom)));
+    var cast = _functionType(
+      typeFormals: [tFrom, tTo],
+      required: [_typeParameterType(tFrom)],
+      returns: _typeParameterType(tTo),
+    );
+    expect(
+        _inferCall(cast, [stringType]), [stringType, iterableType(stringType)]);
   }
 
   void test_boundedByOuterClass() {
     // Regression test for https://github.com/dart-lang/sdk/issues/25740.
 
     // class A {}
-    var a = ElementFactory.classElement('A', objectType);
+    var A = _class(name: 'A', superType: objectType);
+    var typeA = _interfaceType(A);
 
     // class B extends A {}
-    var b = ElementFactory.classElement('B', a.type);
+    var B = _class(name: 'B', superType: typeA);
+    var typeB = _interfaceType(B);
 
     // class C<T extends A> {
-    var c = ElementFactory.classElement('C', objectType, ['T']);
-    (c.typeParameters[0] as TypeParameterElementImpl).bound = a.type;
+    var CT = _typeParameter('T', bound: typeA);
+    var C = _class(
+      name: 'C',
+      superType: objectType,
+      typeParameters: [CT],
+    );
     //   S m<S extends T>(S);
-    var s = TypeBuilder.variable('S');
-    (s.element as TypeParameterElementImpl).bound = c.typeParameters[0].type;
-    var m = ElementFactory.methodElement('m', s, [s]);
-    m.typeParameters = [s.element];
-    c.methods = [m];
+    var S = _typeParameter('S', bound: _typeParameterType(CT));
+    var m = _method(
+      'm',
+      _typeParameterType(S),
+      typeFormals: [S],
+      parameters: [_requiredParameter('_', _typeParameterType(S))],
+    );
+    C.methods = [m];
     // }
 
     // C<Object> cOfObject;
-    var cOfObject = c.type.instantiate([objectType]);
+    var cOfObject = _interfaceType(C, typeArguments: [objectType]);
     // C<A> cOfA;
-    var cOfA = c.type.instantiate([a.type]);
+    var cOfA = _interfaceType(C, typeArguments: [typeA]);
     // C<B> cOfB;
-    var cOfB = c.type.instantiate([b.type]);
+    var cOfB = _interfaceType(C, typeArguments: [typeB]);
     // B b;
     // cOfB.m(b); // infer <B>
-    expect(_inferCall2(cOfB.getMethod('m').type, [b.type]).toString(),
+    expect(_inferCall2(cOfB.getMethod('m').type, [typeB]).toString(),
         'B Function(B)');
     // cOfA.m(b); // infer <B>
-    expect(_inferCall2(cOfA.getMethod('m').type, [b.type]).toString(),
+    expect(_inferCall2(cOfA.getMethod('m').type, [typeB]).toString(),
         'B Function(B)');
     // cOfObject.m(b); // infer <B>
-    expect(_inferCall2(cOfObject.getMethod('m').type, [b.type]).toString(),
+    expect(_inferCall2(cOfObject.getMethod('m').type, [typeB]).toString(),
         'B Function(B)');
   }
 
@@ -906,31 +987,40 @@
     // Regression test for https://github.com/dart-lang/sdk/issues/25740.
 
     // class A {}
-    var a = ElementFactory.classElement('A', objectType);
+    var A = _class(name: 'A', superType: objectType);
+    var typeA = _interfaceType(A);
 
     // class B extends A {}
-    var b = ElementFactory.classElement('B', a.type);
+    var B = _class(name: 'B', superType: typeA);
+    var typeB = _interfaceType(B);
 
     // class C<T extends A> {
-    var c = ElementFactory.classElement('C', objectType, ['T']);
-    (c.typeParameters[0] as TypeParameterElementImpl).bound = a.type;
+    var CT = _typeParameter('T', bound: typeA);
+    var C = _class(
+      name: 'C',
+      superType: objectType,
+      typeParameters: [CT],
+    );
     //   S m<S extends Iterable<T>>(S);
-    var s = TypeBuilder.variable('S');
-    var iterableOfT = iterableType.instantiate([c.typeParameters[0].type]);
-    (s.element as TypeParameterElementImpl).bound = iterableOfT;
-    var m = ElementFactory.methodElement('m', s, [s]);
-    m.typeParameters = [s.element];
-    c.methods = [m];
+    var iterableOfT = iterableType(_typeParameterType(CT));
+    var S = _typeParameter('S', bound: iterableOfT);
+    var m = _method(
+      'm',
+      _typeParameterType(S),
+      typeFormals: [S],
+      parameters: [_requiredParameter('_', _typeParameterType(S))],
+    );
+    C.methods = [m];
     // }
 
     // C<Object> cOfObject;
-    var cOfObject = c.type.instantiate([objectType]);
+    var cOfObject = _interfaceType(C, typeArguments: [objectType]);
     // C<A> cOfA;
-    var cOfA = c.type.instantiate([a.type]);
+    var cOfA = _interfaceType(C, typeArguments: [typeA]);
     // C<B> cOfB;
-    var cOfB = c.type.instantiate([b.type]);
+    var cOfB = _interfaceType(C, typeArguments: [typeB]);
     // List<B> b;
-    var listOfB = listType.instantiate([b.type]);
+    var listOfB = listType(typeB);
     // cOfB.m(b); // infer <B>
     expect(_inferCall2(cOfB.getMethod('m').type, [listOfB]).toString(),
         'List<B> Function(List<B>)');
@@ -943,197 +1033,316 @@
   }
 
   void test_boundedRecursively() {
-    // class Cloneable<T extends Cloneable<T>>
-    ClassElementImpl cloneable =
-        ElementFactory.classElement('Cloneable', objectType, ['T']);
-    (cloneable.typeParameters[0] as TypeParameterElementImpl).bound =
-        cloneable.type;
-    // class Foo extends Cloneable<Foo>
-    ClassElementImpl foo = ElementFactory.classElement('Foo', null);
-    foo.supertype = cloneable.type.instantiate([foo.type]);
+    // class A<T extends A<T>>
+    var T = _typeParameter('T');
+    var A = _class(
+      name: 'Cloneable',
+      superType: objectType,
+      typeParameters: [T],
+    );
+    T.bound = _interfaceType(
+      A,
+      typeArguments: [_typeParameterType(T)],
+    );
 
-    // <S extends Cloneable<S>>
-    var s = TypeBuilder.variable('S');
-    (s.element as TypeParameterElementImpl).bound =
-        cloneable.type.instantiate([s]);
+    // class B extends A<B> {}
+    var B = _class(name: 'B', superType: null);
+    B.supertype = _interfaceType(A, typeArguments: [_interfaceType(B)]);
+    var typeB = _interfaceType(B);
+
+    // <S extends A<S>>
+    var S = _typeParameter('S');
+    var typeS = _typeParameterType(S);
+    S.bound = _interfaceType(A, typeArguments: [typeS]);
+
     // (S, S) -> S
-    var clone = TypeBuilder.function(types: [s], required: [s, s], result: s);
-    expect(_inferCall(clone, [foo.type, foo.type]), [foo.type]);
+    var clone = _functionType(
+      typeFormals: [S],
+      required: [typeS, typeS],
+      returns: typeS,
+    );
+    expect(_inferCall(clone, [typeB, typeB]), [typeB]);
 
     // Something invalid...
-    expect(_inferCall(clone, [stringType, numType], expectError: true),
-        [objectType]);
+    expect(
+      _inferCall(clone, [stringType, numType], expectError: true),
+      [objectType],
+    );
   }
 
   void test_genericCastFunction() {
     // <TFrom, TTo>(TFrom) -> TTo
-    var tFrom = TypeBuilder.variable('TFrom');
-    var tTo = TypeBuilder.variable('TTo');
-    var cast = TypeBuilder.function(
-        types: [tFrom, tTo], required: [tFrom], result: tTo);
+    var tFrom = _typeParameter('TFrom');
+    var tTo = _typeParameter('TTo');
+    var cast = _functionType(
+      typeFormals: [tFrom, tTo],
+      required: [_typeParameterType(tFrom)],
+      returns: _typeParameterType(tTo),
+    );
     expect(_inferCall(cast, [intType]), [intType, dynamicType]);
   }
 
   void test_genericCastFunctionWithUpperBound() {
     // <TFrom, TTo extends TFrom>(TFrom) -> TTo
-    var tFrom = TypeBuilder.variable('TFrom');
-    var tTo = TypeBuilder.variable('TTo', bound: tFrom);
-    var cast = TypeBuilder.function(
-        types: [tFrom, tTo], required: [tFrom], result: tTo);
+    var tFrom = _typeParameter('TFrom');
+    var tTo = _typeParameter('TTo', bound: _typeParameterType(tFrom));
+    var cast = _functionType(
+      typeFormals: [tFrom, tTo],
+      required: [_typeParameterType(tFrom)],
+      returns: _typeParameterType(tTo),
+    );
     expect(_inferCall(cast, [intType]), [intType, intType]);
   }
 
   void test_parametersToFunctionParam() {
     // <T>(f(T t)) -> T
-    var t = TypeBuilder.variable('T');
-    var cast = TypeBuilder.function(types: [
-      t
-    ], required: [
-      TypeBuilder.function(required: [t], result: dynamicType)
-    ], result: t);
+    var T = _typeParameter('T');
+    var cast = _functionType(
+      typeFormals: [T],
+      required: [
+        _functionType(
+          required: [_typeParameterType(T)],
+          returns: dynamicType,
+        )
+      ],
+      returns: _typeParameterType(T),
+    );
     expect(
-        _inferCall(cast, [
-          TypeBuilder.function(required: [numType], result: dynamicType)
-        ]),
-        [numType]);
+      _inferCall(cast, [
+        _functionType(
+          required: [numType],
+          returns: dynamicType,
+        )
+      ]),
+      [numType],
+    );
   }
 
   void test_parametersUseLeastUpperBound() {
     // <T>(T x, T y) -> T
-    var t = TypeBuilder.variable('T');
-    var cast = TypeBuilder.function(types: [t], required: [t, t], result: t);
+    var T = _typeParameter('T');
+    var cast = _functionType(
+      typeFormals: [T],
+      required: [
+        _typeParameterType(T),
+        _typeParameterType(T),
+      ],
+      returns: _typeParameterType(T),
+    );
     expect(_inferCall(cast, [intType, doubleType]), [numType]);
   }
 
   void test_parameterTypeUsesUpperBound() {
     // <T extends num>(T) -> dynamic
-    var t = TypeBuilder.variable('T', bound: numType);
-    var f =
-        TypeBuilder.function(types: [t], required: [t], result: dynamicType);
+    var T = _typeParameter('T', bound: numType);
+    var f = _functionType(
+      typeFormals: [T],
+      required: [
+        _typeParameterType(T),
+      ],
+      returns: dynamicType,
+    );
     expect(_inferCall(f, [intType]), [intType]);
   }
 
   void test_returnFunctionWithGenericParameter() {
     // <T>(T -> T) -> (T -> void)
-    var t = TypeBuilder.variable('T');
-    var f = TypeBuilder.function(types: [
-      t
-    ], required: [
-      TypeBuilder.function(required: [t], result: t)
-    ], result: TypeBuilder.function(required: [t], result: voidType));
+    var T = _typeParameter('T');
+    var f = _functionType(
+      typeFormals: [T],
+      required: [
+        _functionType(
+          required: [
+            _typeParameterType(T),
+          ],
+          returns: _typeParameterType(T),
+        )
+      ],
+      returns: _functionType(
+        required: [
+          _typeParameterType(T),
+        ],
+        returns: voidType,
+      ),
+    );
     expect(
-        _inferCall(f, [
-          TypeBuilder.function(required: [numType], result: intType)
-        ]),
-        [intType]);
+      _inferCall(f, [
+        _functionType(required: [numType], returns: intType)
+      ]),
+      [intType],
+    );
   }
 
   void test_returnFunctionWithGenericParameterAndContext() {
     // <T>(T -> T) -> (T -> Null)
-    var t = TypeBuilder.variable('T');
-    var f = TypeBuilder.function(types: [
-      t
-    ], required: [
-      TypeBuilder.function(required: [t], result: t)
-    ], result: TypeBuilder.function(required: [t], result: nullType));
+    var T = _typeParameter('T');
+    var f = _functionType(
+      typeFormals: [T],
+      required: [
+        _functionType(
+          required: [
+            _typeParameterType(T),
+          ],
+          returns: _typeParameterType(T),
+        )
+      ],
+      returns: _functionType(
+        required: [
+          _typeParameterType(T),
+        ],
+        returns: nullType,
+      ),
+    );
     expect(
-        _inferCall(f, [],
-            returnType:
-                TypeBuilder.function(required: [numType], result: intType)),
-        [numType]);
+      _inferCall(
+        f,
+        [],
+        returnType: _functionType(
+          required: [numType],
+          returns: intType,
+        ),
+      ),
+      [numType],
+    );
   }
 
   void test_returnFunctionWithGenericParameterAndReturn() {
     // <T>(T -> T) -> (T -> T)
-    var t = TypeBuilder.variable('T');
-    var f = TypeBuilder.function(types: [
-      t
-    ], required: [
-      TypeBuilder.function(required: [t], result: t)
-    ], result: TypeBuilder.function(required: [t], result: t));
+    var T = _typeParameter('T');
+    var f = _functionType(
+      typeFormals: [T],
+      required: [
+        _functionType(
+          required: [
+            _typeParameterType(T),
+          ],
+          returns: _typeParameterType(T),
+        )
+      ],
+      returns: _functionType(
+        required: [
+          _typeParameterType(T),
+        ],
+        returns: _typeParameterType(T),
+      ),
+    );
     expect(
-        _inferCall(f, [
-          TypeBuilder.function(required: [numType], result: intType)
-        ]),
-        [intType]);
+      _inferCall(f, [
+        _functionType(
+          required: [numType],
+          returns: intType,
+        )
+      ]),
+      [intType],
+    );
   }
 
   void test_returnFunctionWithGenericReturn() {
     // <T>(T -> T) -> (() -> T)
-    var t = TypeBuilder.variable('T');
-    var f = TypeBuilder.function(types: [
-      t
-    ], required: [
-      TypeBuilder.function(required: [t], result: t)
-    ], result: TypeBuilder.function(required: [], result: t));
+    var T = _typeParameter('T');
+    var f = _functionType(
+      typeFormals: [T],
+      required: [
+        _functionType(
+          required: [
+            _typeParameterType(T),
+          ],
+          returns: _typeParameterType(T),
+        )
+      ],
+      returns: _functionType(
+        returns: _typeParameterType(T),
+      ),
+    );
     expect(
-        _inferCall(f, [
-          TypeBuilder.function(required: [numType], result: intType)
-        ]),
-        [intType]);
+      _inferCall(f, [
+        _functionType(
+          required: [numType],
+          returns: intType,
+        )
+      ]),
+      [intType],
+    );
   }
 
   void test_returnTypeFromContext() {
     // <T>() -> T
-    var t = TypeBuilder.variable('T');
-    var f = TypeBuilder.function(types: [t], required: [], result: t);
+    var T = _typeParameter('T');
+    var f = _functionType(
+      typeFormals: [T],
+      returns: _typeParameterType(T),
+    );
     expect(_inferCall(f, [], returnType: stringType), [stringType]);
   }
 
   void test_returnTypeWithBoundFromContext() {
     // <T extends num>() -> T
-    var t = TypeBuilder.variable('T', bound: numType);
-    var f = TypeBuilder.function(types: [t], required: [], result: t);
+    var T = _typeParameter('T', bound: numType);
+    var f = _functionType(
+      typeFormals: [T],
+      returns: _typeParameterType(T),
+    );
     expect(_inferCall(f, [], returnType: doubleType), [doubleType]);
   }
 
   void test_returnTypeWithBoundFromInvalidContext() {
     // <T extends num>() -> T
-    var t = TypeBuilder.variable('T', bound: numType);
-    var f = TypeBuilder.function(types: [t], required: [], result: t);
+    var T = _typeParameter('T', bound: numType);
+    var f = _functionType(
+      typeFormals: [T],
+      returns: _typeParameterType(T),
+    );
     expect(_inferCall(f, [], returnType: stringType), [nullType]);
   }
 
   void test_unifyParametersToFunctionParam() {
     // <T>(f(T t), g(T t)) -> T
-    var t = TypeBuilder.variable('T');
-    var cast = TypeBuilder.function(types: [
-      t
-    ], required: [
-      TypeBuilder.function(required: [t], result: dynamicType),
-      TypeBuilder.function(required: [t], result: dynamicType)
-    ], result: t);
+    var T = _typeParameter('T');
+    var cast = _functionType(
+      typeFormals: [T],
+      required: [
+        _functionType(
+          required: [_typeParameterType(T)],
+          returns: dynamicType,
+        ),
+        _functionType(
+          required: [_typeParameterType(T)],
+          returns: dynamicType,
+        )
+      ],
+      returns: _typeParameterType(T),
+    );
     expect(
-        _inferCall(cast, [
-          TypeBuilder.function(required: [intType], result: dynamicType),
-          TypeBuilder.function(required: [doubleType], result: dynamicType)
-        ]),
-        [nullType]);
+      _inferCall(cast, [
+        _functionType(required: [intType], returns: dynamicType),
+        _functionType(required: [doubleType], returns: dynamicType)
+      ]),
+      [nullType],
+    );
   }
 
   void test_unusedReturnTypeIsDynamic() {
     // <T>() -> T
-    var t = TypeBuilder.variable('T');
-    var f = TypeBuilder.function(types: [t], required: [], result: t);
+    var T = _typeParameter('T');
+    var f = _functionType(
+      typeFormals: [T],
+      returns: _typeParameterType(T),
+    );
     expect(_inferCall(f, []), [dynamicType]);
   }
 
   void test_unusedReturnTypeWithUpperBound() {
     // <T extends num>() -> T
-    var t = TypeBuilder.variable('T', bound: numType);
-    var f = TypeBuilder.function(types: [t], required: [], result: t);
+    var T = _typeParameter('T', bound: numType);
+    var f = _functionType(
+      typeFormals: [T],
+      returns: _typeParameterType(T),
+    );
     expect(_inferCall(f, []), [numType]);
   }
 
   List<DartType> _inferCall(FunctionTypeImpl ft, List<DartType> arguments,
       {DartType returnType, bool expectError: false}) {
-    FunctionType inferred = _inferCall2(ft, arguments,
-        returnType: returnType, expectError: expectError);
-    return inferred?.typeArguments;
-  }
-
-  FunctionType _inferCall2(FunctionTypeImpl ft, List<DartType> arguments,
-      {DartType returnType, bool expectError: false}) {
     var listener = new RecordingErrorListener();
 
     var reporter = new ErrorReporter(
@@ -1141,10 +1350,15 @@
         new NonExistingSource(
             '/test.dart', toUri('/test.dart'), UriKind.FILE_URI));
 
-    FunctionType inferred = typeSystem.inferGenericFunctionOrType(
-        ft, ft.parameters, arguments, returnType,
-        errorReporter: reporter,
-        errorNode: astFactory.nullLiteral(new KeywordToken(Keyword.NULL, 0)));
+    var typeArguments = typeSystem.inferGenericFunctionOrType(
+      typeParameters: ft.typeFormals,
+      parameters: ft.parameters,
+      declaredReturnType: ft.returnType,
+      argumentTypes: arguments,
+      contextReturnType: returnType,
+      errorReporter: reporter,
+      errorNode: astFactory.nullLiteral(new KeywordToken(Keyword.NULL, 0)),
+    );
 
     if (expectError) {
       expect(listener.errors.map((e) => e.errorCode).toList(),
@@ -1153,44 +1367,47 @@
     } else {
       expect(listener.errors, isEmpty, reason: 'did not expect any errors.');
     }
-    return inferred;
+    return typeArguments;
+  }
+
+  FunctionType _inferCall2(FunctionTypeImpl ft, List<DartType> arguments,
+      {DartType returnType, bool expectError: false}) {
+    var typeArguments = _inferCall(
+      ft,
+      arguments,
+      returnType: returnType,
+      expectError: expectError,
+    );
+    return ft.instantiate(typeArguments);
   }
 }
 
 @reflectiveTest
 class GreatestLowerBoundTest extends BoundTestBase {
-  void setUp() {
-    super.setUp();
-    typeSystem = new Dart2TypeSystem(typeProvider);
-  }
-
   void test_bottom_function() {
-    _checkGreatestLowerBound(bottomType, simpleFunctionType, bottomType);
+    _checkGreatestLowerBound(bottomType, _functionType(), bottomType);
   }
 
   void test_bottom_interface() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
-    _checkGreatestLowerBound(bottomType, interfaceType, bottomType);
+    var A = _class(name: 'A');
+    _checkGreatestLowerBound(bottomType, _interfaceType(A), bottomType);
   }
 
   void test_bottom_typeParam() {
-    DartType typeParam = ElementFactory.typeParameterElement('T').type;
-    _checkGreatestLowerBound(bottomType, typeParam, bottomType);
+    var T = _typeParameter('T');
+    _checkGreatestLowerBound(bottomType, _typeParameterType(T), bottomType);
   }
 
   void test_bounds_of_top_types_complete() {
     // Test every combination of a subset of Tops programatically.
-    final futureOrDynamicType = futureOrType.instantiate([dynamicType]);
-    final futureOrObjectType = futureOrType.instantiate([objectType]);
-    final futureOrVoidType = futureOrType.instantiate([voidType]);
-    final futureOrFutureOrDynamicType =
-        futureOrType.instantiate([futureOrDynamicType]);
-    final futureOrFutureOrObjectType =
-        futureOrType.instantiate([futureOrObjectType]);
-    final futureOrFutureOrVoidType =
-        futureOrType.instantiate([futureOrVoidType]);
+    var futureOrDynamicType = futureOrType(dynamicType);
+    var futureOrObjectType = futureOrType(objectType);
+    var futureOrVoidType = futureOrType(voidType);
+    final futureOrFutureOrDynamicType = futureOrType(futureOrDynamicType);
+    final futureOrFutureOrObjectType = futureOrType(futureOrObjectType);
+    final futureOrFutureOrVoidType = futureOrType(futureOrVoidType);
 
-    final orderedTops = [
+    var orderedTops = [
       // Lower index, so lower Top
       voidType,
       dynamicType,
@@ -1225,9 +1442,8 @@
   }
 
   void test_bounds_of_top_types_sanity() {
-    final futureOrDynamicType = futureOrType.instantiate([dynamicType]);
-    final futureOrFutureOrDynamicType =
-        futureOrType.instantiate([futureOrDynamicType]);
+    var futureOrDynamicType = futureOrType(dynamicType);
+    final futureOrFutureOrDynamicType = futureOrType(futureOrDynamicType);
 
     // Sanity check specific cases of top for GLB/LUB.
     _checkLeastUpperBound(objectType, dynamicType, dynamicType);
@@ -1244,22 +1460,28 @@
     // class A
     // class B extends A
     // class C extends B
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement("C", classB.type);
-    _checkGreatestLowerBound(classA.type, classC.type, classC.type);
+    var A = _class(name: 'A');
+    var B = _class(name: 'B', superType: _interfaceType(A));
+    var C = _class(name: 'C', superType: _interfaceType(B));
+    _checkGreatestLowerBound(
+      _interfaceType(A),
+      _interfaceType(C),
+      _interfaceType(C),
+    );
   }
 
   void test_classAndSuperinterface() {
     // class A
     // class B implements A
     // class C implements B
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    ClassElementImpl classC = ElementFactory.classElement2("C");
-    classB.interfaces = <InterfaceType>[classA.type];
-    classC.interfaces = <InterfaceType>[classB.type];
-    _checkGreatestLowerBound(classA.type, classC.type, classC.type);
+    var A = _class(name: 'A');
+    var B = _class(name: 'B', interfaces: [_interfaceType(A)]);
+    var C = _class(name: 'C', interfaces: [_interfaceType(B)]);
+    _checkGreatestLowerBound(
+      _interfaceType(A),
+      _interfaceType(C),
+      _interfaceType(C),
+    );
   }
 
   void test_dynamic_bottom() {
@@ -1267,18 +1489,19 @@
   }
 
   void test_dynamic_function() {
-    _checkGreatestLowerBound(
-        dynamicType, simpleFunctionType, simpleFunctionType);
+    _checkGreatestLowerBound(dynamicType, _functionType(), _functionType());
   }
 
   void test_dynamic_interface() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
-    _checkGreatestLowerBound(dynamicType, interfaceType, interfaceType);
+    var A = _class(name: 'A');
+    var typeA = _interfaceType(A);
+    _checkGreatestLowerBound(dynamicType, typeA, typeA);
   }
 
   void test_dynamic_typeParam() {
-    DartType typeParam = ElementFactory.typeParameterElement('T').type;
-    _checkGreatestLowerBound(dynamicType, typeParam, typeParam);
+    var T = _typeParameter('T');
+    var typeT = _typeParameterType(T);
+    _checkGreatestLowerBound(dynamicType, typeT, typeT);
   }
 
   void test_dynamic_void() {
@@ -1304,7 +1527,6 @@
       optional: [intType],
     );
     var type2 = _functionType(
-      required: [],
       optional: [doubleType, stringType, objectType],
     );
     var expected = _functionType(
@@ -1404,7 +1626,6 @@
       named: {'a': intType},
     );
     var type2 = _functionType(
-      required: [],
       named: {'a': intType},
     );
     _checkGreatestLowerBound(type1, type2, bottomType);
@@ -1455,8 +1676,9 @@
   }
 
   void test_interface_function() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
-    _checkGreatestLowerBound(interfaceType, simpleFunctionType, bottomType);
+    var A = _class(name: 'A');
+    var typeA = _interfaceType(A);
+    _checkGreatestLowerBound(typeA, _functionType(), bottomType);
   }
 
   void test_mixin() {
@@ -1464,27 +1686,38 @@
     // class B
     // class C
     // class D extends A with B, C
-    ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classB = ElementFactory.classElement2("B");
-    ClassElement classC = ElementFactory.classElement2("C");
-    ClassElementImpl classD = ElementFactory.classElement("D", classA.type);
-    classD.mixins = <InterfaceType>[classB.type, classC.type];
-    _checkGreatestLowerBound(classA.type, classD.type, classD.type);
-    _checkGreatestLowerBound(classB.type, classD.type, classD.type);
-    _checkGreatestLowerBound(classC.type, classD.type, classD.type);
+    var A = _class(name: 'A');
+    var typeA = _interfaceType(A);
+
+    var B = _class(name: 'B');
+    var typeB = _interfaceType(B);
+
+    var C = _class(name: 'C');
+    var typeC = _interfaceType(C);
+
+    var D = _class(
+      name: 'D',
+      superType: _interfaceType(A),
+      mixins: [typeB, typeC],
+    );
+    var typeD = _interfaceType(D);
+
+    _checkGreatestLowerBound(typeA, typeD, typeD);
+    _checkGreatestLowerBound(typeB, typeD, typeD);
+    _checkGreatestLowerBound(typeC, typeD, typeD);
   }
 
   void test_self() {
-    DartType typeParam = ElementFactory.typeParameterElement('T').type;
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    var T = _typeParameter('T');
+    var A = _class(name: 'A');
 
     List<DartType> types = [
       dynamicType,
       voidType,
       bottomType,
-      typeParam,
-      interfaceType,
-      simpleFunctionType
+      _typeParameterType(T),
+      _interfaceType(A),
+      _functionType(),
     ];
 
     for (DartType type in types) {
@@ -1493,39 +1726,50 @@
   }
 
   void test_typeParam_function_noBound() {
-    DartType typeParam = ElementFactory.typeParameterElement('T').type;
-    _checkGreatestLowerBound(typeParam, simpleFunctionType, bottomType);
+    var T = _typeParameter('T');
+    _checkGreatestLowerBound(
+      _typeParameterType(T),
+      _functionType(),
+      bottomType,
+    );
   }
 
   void test_typeParam_interface_bounded() {
-    DartType typeA = ElementFactory.classElement2('A', []).type;
-    DartType typeB = ElementFactory.classElement('B', typeA).type;
-    DartType typeC = ElementFactory.classElement('C', typeB).type;
-    TypeParameterElementImpl typeParam =
-        ElementFactory.typeParameterElement('T');
-    typeParam.bound = typeB;
-    _checkGreatestLowerBound(typeParam.type, typeC, bottomType);
+    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: typeB);
+    var typeC = _interfaceType(C);
+
+    var T = _typeParameter('T', bound: typeB);
+    _checkGreatestLowerBound(_typeParameterType(T), typeC, bottomType);
   }
 
   void test_typeParam_interface_noBound() {
     // GLB(T, A) = ⊥
-    DartType typeParam = ElementFactory.typeParameterElement('T').type;
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
-    _checkGreatestLowerBound(typeParam, interfaceType, bottomType);
+    var T = _typeParameter('T');
+    var A = _class(name: 'A');
+    _checkGreatestLowerBound(
+      _typeParameterType(T),
+      _interfaceType(A),
+      bottomType,
+    );
   }
 
   void test_typeParameters_different() {
     // GLB(List<int>, List<double>) = ⊥
-    InterfaceType listOfIntType = listType.instantiate(<DartType>[intType]);
-    InterfaceType listOfDoubleType =
-        listType.instantiate(<DartType>[doubleType]);
+    var listOfIntType = listType(intType);
+    var listOfDoubleType = listType(doubleType);
     // TODO(rnystrom): Can we do something better here?
     _checkGreatestLowerBound(listOfIntType, listOfDoubleType, bottomType);
   }
 
   void test_typeParameters_same() {
     // GLB(List<int>, List<int>) = List<int>
-    InterfaceType listOfIntType = listType.instantiate(<DartType>[intType]);
+    var listOfIntType = listType(intType);
     _checkGreatestLowerBound(listOfIntType, listOfIntType, listOfIntType);
   }
 
@@ -1533,23 +1777,25 @@
     // class A
     // class B
     // class C
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    _checkGreatestLowerBound(classA.type, classB.type, bottomType);
+    var A = _class(name: 'A');
+    var B = _class(name: 'B');
+    _checkGreatestLowerBound(_interfaceType(A), _interfaceType(B), bottomType);
   }
 
   void test_void() {
+    var A = _class(name: 'A');
+    var T = _typeParameter('T');
     List<DartType> types = [
       bottomType,
-      simpleFunctionType,
-      ElementFactory.classElement2('A', []).type,
-      ElementFactory.typeParameterElement('T').type
+      _functionType(),
+      _interfaceType(A),
+      _typeParameterType(T),
     ];
     for (DartType type in types) {
       _checkGreatestLowerBound(
-        _functionType(required: [], returns: voidType),
-        _functionType(required: [], returns: type),
-        _functionType(required: [], returns: type),
+        _functionType(returns: voidType),
+        _functionType(returns: type),
+        _functionType(returns: type),
       );
     }
   }
@@ -1557,11 +1803,6 @@
 
 @reflectiveTest
 class LeastUpperBoundFunctionsTest extends BoundTestBase {
-  void setUp() {
-    super.setUp();
-    typeSystem = new Dart2TypeSystem(typeProvider);
-  }
-
   void test_differentRequiredArity() {
     var type1 = _functionType(required: [intType, intType]);
     var type2 = _functionType(required: [intType, intType, intType]);
@@ -1692,18 +1933,27 @@
   }
 
   void test_typeFormals_differentBounds() {
-    var T1 = _typeParameterElement('T1', bound: intType);
-    var type1 = _functionType(typeFormals: [T1], returns: T1.type);
+    var T1 = _typeParameter('T1', bound: intType);
+    var type1 = _functionType(
+      typeFormals: [T1],
+      returns: _typeParameterType(T1),
+    );
 
-    var T2 = _typeParameterElement('T2', bound: doubleType);
-    var type2 = _functionType(typeFormals: [T2], returns: T2.type);
+    var T2 = _typeParameter('T2', bound: doubleType);
+    var type2 = _functionType(
+      typeFormals: [T2],
+      returns: _typeParameterType(T2),
+    );
 
     _checkLeastUpperBound(type1, type2, functionType);
   }
 
   void test_typeFormals_differentNumber() {
-    var T1 = _typeParameterElement('T1', bound: numType);
-    var type1 = _functionType(typeFormals: [T1], returns: T1.type);
+    var T1 = _typeParameter('T1', bound: numType);
+    var type1 = _functionType(
+      typeFormals: [T1],
+      returns: _typeParameterType(T1),
+    );
 
     var type2 = _functionType(returns: intType);
 
@@ -1711,14 +1961,23 @@
   }
 
   void test_typeFormals_sameBounds() {
-    var T1 = _typeParameterElement('T1', bound: numType);
-    var type1 = _functionType(typeFormals: [T1], returns: T1.type);
+    var T1 = _typeParameter('T1', bound: numType);
+    var type1 = _functionType(
+      typeFormals: [T1],
+      returns: _typeParameterType(T1),
+    );
 
-    var T2 = _typeParameterElement('T2', bound: numType);
-    var type2 = _functionType(typeFormals: [T2], returns: T2.type);
+    var T2 = _typeParameter('T2', bound: numType);
+    var type2 = _functionType(
+      typeFormals: [T2],
+      returns: _typeParameterType(T2),
+    );
 
-    var TE = _typeParameterElement('T', bound: numType);
-    var expected = _functionType(typeFormals: [TE], returns: TE.type);
+    var TE = _typeParameter('T', bound: numType);
+    var expected = _functionType(
+      typeFormals: [TE],
+      returns: _typeParameterType(TE),
+    );
 
     _checkLeastUpperBound(type1, type2, expected);
   }
@@ -1726,37 +1985,36 @@
 
 @reflectiveTest
 class LeastUpperBoundTest extends BoundTestBase {
-  void setUp() {
-    super.setUp();
-    typeSystem = new Dart2TypeSystem(typeProvider);
-  }
-
   void test_bottom_function() {
-    _checkLeastUpperBound(bottomType, simpleFunctionType, simpleFunctionType);
+    _checkLeastUpperBound(bottomType, _functionType(), _functionType());
   }
 
   void test_bottom_interface() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
-    _checkLeastUpperBound(bottomType, interfaceType, interfaceType);
+    var A = _class(name: 'A');
+    var typeA = _interfaceType(A);
+    _checkLeastUpperBound(bottomType, typeA, typeA);
   }
 
   void test_bottom_typeParam() {
-    DartType typeParam = ElementFactory.typeParameterElement('T').type;
-    _checkLeastUpperBound(bottomType, typeParam, typeParam);
+    var T = _typeParameter('T');
+    var typeT = _typeParameterType(T);
+    _checkLeastUpperBound(bottomType, typeT, typeT);
   }
 
   void test_directInterfaceCase() {
     // class A
     // class B implements A
     // class C implements B
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    ClassElementImpl classC = ElementFactory.classElement2("C");
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
-    classB.interfaces = <InterfaceType>[typeA];
-    classC.interfaces = <InterfaceType>[typeB];
+
+    var A = _class(name: 'A');
+    var typeA = _interfaceType(A);
+
+    var B = _class(name: 'B', interfaces: [typeA]);
+    var typeB = _interfaceType(B);
+
+    var C = _class(name: 'C', interfaces: [typeB]);
+    var typeC = _interfaceType(C);
+
     _checkLeastUpperBound(typeB, typeC, typeB);
   }
 
@@ -1764,44 +2022,49 @@
     // class A
     // class B extends A
     // class C extends B
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement("C", classB.type);
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
+
+    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: typeB);
+    var typeC = _interfaceType(C);
+
     _checkLeastUpperBound(typeB, typeC, typeB);
   }
 
   void test_directSuperclass_nullability() {
-    ClassElement _classElement(String name, InterfaceType supertype) {
-      return ElementFactory.classElement3(name: name, supertype: supertype);
-    }
+    var aElement = _class(name: 'A');
+    var aQuestion = _interfaceType(
+      aElement,
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+    var aStar = _interfaceType(
+      aElement,
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+    var aNone = _interfaceType(
+      aElement,
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
 
-    InterfaceTypeImpl _interfaceType(
-      ClassElement element,
-      NullabilitySuffix nullabilitySuffix,
-    ) {
-      return InterfaceTypeImpl.explicit(
-        element,
-        const [],
-        nullabilitySuffix: nullabilitySuffix,
+    var bElementStar = _class(name: 'B', superType: aStar);
+    var bElementNone = _class(name: 'B', superType: aNone);
+
+    InterfaceTypeImpl _bTypeStarElement(NullabilitySuffix nullability) {
+      return _interfaceType(
+        bElementStar,
+        nullabilitySuffix: nullability,
       );
     }
 
-    var aElement = ElementFactory.classElement3(name: 'A');
-    var aQuestion = _interfaceType(aElement, NullabilitySuffix.question);
-    var aStar = _interfaceType(aElement, NullabilitySuffix.star);
-    var aNone = _interfaceType(aElement, NullabilitySuffix.none);
-
-    var bElementStar = _classElement('B', aStar);
-    var bElementNone = _classElement('B', aNone);
-
-    InterfaceTypeImpl _bTypeStarElement(NullabilitySuffix nullability) {
-      return _interfaceType(bElementStar, nullability);
-    }
-
     InterfaceTypeImpl _bTypeNoneElement(NullabilitySuffix nullability) {
-      return _interfaceType(bElementNone, nullability);
+      return _interfaceType(
+        bElementNone,
+        nullabilitySuffix: nullability,
+      );
     }
 
     var bStarQuestion = _bTypeStarElement(NullabilitySuffix.question);
@@ -1847,17 +2110,17 @@
   }
 
   void test_dynamic_function() {
-    _checkLeastUpperBound(dynamicType, simpleFunctionType, dynamicType);
+    _checkLeastUpperBound(dynamicType, _functionType(), dynamicType);
   }
 
   void test_dynamic_interface() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
-    _checkLeastUpperBound(dynamicType, interfaceType, dynamicType);
+    var A = _class(name: 'A');
+    _checkLeastUpperBound(dynamicType, _interfaceType(A), dynamicType);
   }
 
   void test_dynamic_typeParam() {
-    DartType typeParam = ElementFactory.typeParameterElement('T').type;
-    _checkLeastUpperBound(dynamicType, typeParam, dynamicType);
+    var T = _typeParameter('T');
+    _checkLeastUpperBound(dynamicType, _typeParameterType(T), dynamicType);
   }
 
   void test_dynamic_void() {
@@ -1866,27 +2129,25 @@
   }
 
   void test_interface_function() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
-    _checkLeastUpperBound(interfaceType, simpleFunctionType, objectType);
+    var A = _class(name: 'A');
+    _checkLeastUpperBound(_interfaceType(A), _functionType(), objectType);
   }
 
   void test_interface_sameElement_nullability() {
-    var aElement = ElementFactory.classElement3(name: 'A');
+    var aElement = _class(name: 'A');
 
-    InterfaceTypeImpl _interfaceType(
-      ClassElement element,
-      NullabilitySuffix nullabilitySuffix,
-    ) {
-      return InterfaceTypeImpl.explicit(
-        element,
-        const [],
-        nullabilitySuffix: nullabilitySuffix,
-      );
-    }
-
-    var aQuestion = _interfaceType(aElement, NullabilitySuffix.question);
-    var aStar = _interfaceType(aElement, NullabilitySuffix.star);
-    var aNone = _interfaceType(aElement, NullabilitySuffix.none);
+    var aQuestion = _interfaceType(
+      aElement,
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+    var aStar = _interfaceType(
+      aElement,
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+    var aNone = _interfaceType(
+      aElement,
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
 
     void assertLUB(DartType type1, DartType type2, DartType expected) {
       expect(typeSystem.getLeastUpperBound(type1, type2), expected);
@@ -1907,10 +2168,10 @@
   }
 
   void test_mixinAndClass_constraintAndInterface() {
-    var classA = ElementFactory.classElement3(name: 'A');
+    var classA = _class(name: 'A');
     var instA = InstantiatedClass(classA, []);
 
-    var classB = ElementFactory.classElement3(
+    var classB = _class(
       name: 'B',
       interfaces: [instA.withNullabilitySuffixNone],
     );
@@ -1921,14 +2182,12 @@
     );
 
     _checkLeastUpperBound(
-      InterfaceTypeImpl.explicit(
+      _interfaceType(
         classB,
-        [],
         nullabilitySuffix: NullabilitySuffix.star,
       ),
-      InterfaceTypeImpl.explicit(
+      _interfaceType(
         mixinM,
-        [],
         nullabilitySuffix: NullabilitySuffix.star,
       ),
       instA.withNullability(NullabilitySuffix.star),
@@ -1936,21 +2195,21 @@
   }
 
   void test_mixinAndClass_object() {
-    var classA = ElementFactory.classElement3(name: 'A');
+    var classA = _class(name: 'A');
     var mixinM = ElementFactory.mixinElement(name: 'M');
 
     _checkLeastUpperBound(
-      InterfaceTypeImpl.explicit(classA, []),
-      InterfaceTypeImpl.explicit(mixinM, []),
-      typeProvider.objectType,
+      _interfaceType(classA),
+      _interfaceType(mixinM),
+      objectType,
     );
   }
 
   void test_mixinAndClass_sharedInterface() {
-    var classA = ElementFactory.classElement3(name: 'A');
+    var classA = _class(name: 'A');
     var instA = InstantiatedClass(classA, []);
 
-    var classB = ElementFactory.classElement3(
+    var classB = _class(
       name: 'B',
       interfaces: [instA.withNullabilitySuffixNone],
     );
@@ -1961,14 +2220,12 @@
     );
 
     _checkLeastUpperBound(
-      InterfaceTypeImpl.explicit(
+      _interfaceType(
         classB,
-        [],
         nullabilitySuffix: NullabilitySuffix.star,
       ),
-      InterfaceTypeImpl.explicit(
+      _interfaceType(
         mixinM,
-        [],
         nullabilitySuffix: NullabilitySuffix.star,
       ),
       instA.withNullability(NullabilitySuffix.star),
@@ -1980,19 +2237,28 @@
     // class B extends A
     // class C extends A
     // class D extends B with M, N, O, P
-    ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classB = ElementFactory.classElement("B", classA.type);
-    ClassElement classC = ElementFactory.classElement("C", classA.type);
-    ClassElementImpl classD = ElementFactory.classElement("D", classB.type);
-    InterfaceType typeA = classA.type;
-    InterfaceType typeC = classC.type;
-    InterfaceType typeD = classD.type;
-    classD.mixins = <InterfaceType>[
-      ElementFactory.classElement2("M").type,
-      ElementFactory.classElement2("N").type,
-      ElementFactory.classElement2("O").type,
-      ElementFactory.classElement2("P").type
-    ];
+
+    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: typeB,
+      mixins: [
+        _interfaceType(_class(name: 'M')),
+        _interfaceType(_class(name: 'N')),
+        _interfaceType(_class(name: 'O')),
+        _interfaceType(_class(name: 'P')),
+      ],
+    );
+    var typeD = _interfaceType(D);
+
     _checkLeastUpperBound(typeD, typeC, typeA);
   }
 
@@ -2016,17 +2282,17 @@
   }
 
   void test_nestedNestedFunctionsGlbInnermostParamTypes() {
-    FunctionType type1 = _functionType(required: [
+    var type1 = _functionType(required: [
       _functionType(required: [
         _functionType(required: [stringType, intType, intType])
       ])
     ]);
-    FunctionType type2 = _functionType(required: [
+    var type2 = _functionType(required: [
       _functionType(required: [
         _functionType(required: [intType, doubleType, numType])
       ])
     ]);
-    FunctionType expected = _functionType(required: [
+    var expected = _functionType(required: [
       _functionType(required: [
         _functionType(required: [bottomType, bottomType, intType])
       ])
@@ -2035,13 +2301,13 @@
   }
 
   void test_object() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    DartType typeObject = typeA.element.supertype;
+    var A = _class(name: 'A');
+    var B = _class(name: 'B');
+    var typeA = _interfaceType(A);
+    var typeB = _interfaceType(B);
+    var typeObject = typeA.element.supertype;
     // assert that object does not have a super type
-    expect((typeObject.element as ClassElement).supertype, isNull);
+    expect(typeObject.element.supertype, isNull);
     // assert that both A and B have the same super type of Object
     expect(typeB.element.supertype, typeObject);
     // finally, assert that the only least upper bound of A and B is Object
@@ -2049,16 +2315,16 @@
   }
 
   void test_self() {
-    DartType typeParam = ElementFactory.typeParameterElement('T').type;
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    var T = _typeParameter('T');
+    var A = _class(name: 'A');
 
     List<DartType> types = [
       dynamicType,
       voidType,
       bottomType,
-      typeParam,
-      interfaceType,
-      simpleFunctionType
+      _typeParameterType(T),
+      _interfaceType(A),
+      _functionType()
     ];
 
     for (DartType type in types) {
@@ -2067,49 +2333,51 @@
   }
 
   void test_sharedSuperclass1() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement("C", classA.type);
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
+    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);
+
     _checkLeastUpperBound(typeB, typeC, typeA);
   }
 
   void test_sharedSuperclass1_nullability() {
-    ClassElementImpl _classElement(String name, InterfaceType supertype) {
-      return ElementFactory.classElement3(name: name, supertype: supertype);
-    }
+    var aElement = _class(name: 'A');
+    var aQuestion = _interfaceType(
+      aElement,
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+    var aStar = _interfaceType(
+      aElement,
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+    var aNone = _interfaceType(
+      aElement,
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
 
-    InterfaceTypeImpl _interfaceType(
-      ClassElement element,
-      NullabilitySuffix nullabilitySuffix,
-    ) {
-      return InterfaceTypeImpl.explicit(
-        element,
-        const [],
-        nullabilitySuffix: nullabilitySuffix,
+    var bElementNone = _class(name: 'B', superType: aNone);
+    var bElementStar = _class(name: 'B', superType: aStar);
+
+    var cElementNone = _class(name: 'C', superType: aNone);
+    var cElementStar = _class(name: 'C', superType: aStar);
+
+    InterfaceTypeImpl bTypeElementNone(NullabilitySuffix nullability) {
+      return _interfaceType(
+        bElementNone,
+        nullabilitySuffix: nullability,
       );
     }
 
-    var aElement = _classElement('A', null);
-
-    var aQuestion = _interfaceType(aElement, NullabilitySuffix.question);
-    var aStar = _interfaceType(aElement, NullabilitySuffix.star);
-    var aNone = _interfaceType(aElement, NullabilitySuffix.none);
-
-    var bElementNone = _classElement('B', aNone);
-    var bElementStar = _classElement('B', aStar);
-
-    var cElementNone = _classElement('C', aNone);
-    var cElementStar = _classElement('C', aStar);
-
-    InterfaceTypeImpl bTypeElementNone(NullabilitySuffix nullability) {
-      return _interfaceType(bElementNone, nullability);
-    }
-
     InterfaceTypeImpl bTypeElementStar(NullabilitySuffix nullability) {
-      return _interfaceType(bElementStar, nullability);
+      return _interfaceType(
+        bElementStar,
+        nullabilitySuffix: nullability,
+      );
     }
 
     var bNoneQuestion = bTypeElementNone(NullabilitySuffix.question);
@@ -2121,11 +2389,17 @@
     var bStarNone = bTypeElementStar(NullabilitySuffix.none);
 
     InterfaceTypeImpl cTypeElementNone(NullabilitySuffix nullability) {
-      return _interfaceType(cElementNone, nullability);
+      return _interfaceType(
+        cElementNone,
+        nullabilitySuffix: nullability,
+      );
     }
 
     InterfaceTypeImpl cTypeElementStar(NullabilitySuffix nullability) {
-      return _interfaceType(cElementStar, nullability);
+      return _interfaceType(
+        cElementStar,
+        nullabilitySuffix: nullability,
+      );
     }
 
     var cNoneQuestion = cTypeElementNone(NullabilitySuffix.question);
@@ -2185,98 +2459,117 @@
   }
 
   void test_sharedSuperclass2() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement("C", classA.type);
-    ClassElementImpl classD = ElementFactory.classElement("D", classC.type);
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeD = classD.type;
+    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: typeC);
+    var typeD = _interfaceType(D);
+
     _checkLeastUpperBound(typeB, typeD, typeA);
   }
 
   void test_sharedSuperclass3() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement("C", classB.type);
-    ClassElementImpl classD = ElementFactory.classElement("D", classB.type);
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
-    InterfaceType typeD = classD.type;
+    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: typeB);
+    var typeC = _interfaceType(C);
+
+    var D = _class(name: 'D', superType: typeB);
+    var typeD = _interfaceType(D);
+
     _checkLeastUpperBound(typeC, typeD, typeB);
   }
 
   void test_sharedSuperclass4() {
-    ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classA2 = ElementFactory.classElement2("A2");
-    ClassElement classA3 = ElementFactory.classElement2("A3");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement("C", classA.type);
-    InterfaceType typeA = classA.type;
-    InterfaceType typeA2 = classA2.type;
-    InterfaceType typeA3 = classA3.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
-    classB.interfaces = <InterfaceType>[typeA2];
-    classC.interfaces = <InterfaceType>[typeA3];
+    var A = _class(name: 'A');
+    var typeA = _interfaceType(A);
+
+    var A2 = _class(name: 'A2');
+    var typeA2 = _interfaceType(A2);
+
+    var A3 = _class(name: 'A3');
+    var typeA3 = _interfaceType(A3);
+
+    var B = _class(name: 'B', superType: typeA, interfaces: [typeA2]);
+    var typeB = _interfaceType(B);
+
+    var C = _class(name: 'C', superType: typeA, interfaces: [typeA3]);
+    var typeC = _interfaceType(C);
+
     _checkLeastUpperBound(typeB, typeC, typeA);
   }
 
   void test_sharedSuperinterface1() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    ClassElementImpl classC = ElementFactory.classElement2("C");
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
-    classB.interfaces = <InterfaceType>[typeA];
-    classC.interfaces = <InterfaceType>[typeA];
+    var A = _class(name: 'A');
+    var typeA = _interfaceType(A);
+
+    var B = _class(name: 'B', interfaces: [typeA]);
+    var typeB = _interfaceType(B);
+
+    var C = _class(name: 'C', interfaces: [typeA]);
+    var typeC = _interfaceType(C);
+
     _checkLeastUpperBound(typeB, typeC, typeA);
   }
 
   void test_sharedSuperinterface2() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    ClassElementImpl classC = ElementFactory.classElement2("C");
-    ClassElementImpl classD = ElementFactory.classElement2("D");
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
-    InterfaceType typeD = classD.type;
-    classB.interfaces = <InterfaceType>[typeA];
-    classC.interfaces = <InterfaceType>[typeA];
-    classD.interfaces = <InterfaceType>[typeC];
+    var A = _class(name: 'A');
+    var typeA = _interfaceType(A);
+
+    var B = _class(name: 'B', interfaces: [typeA]);
+    var typeB = _interfaceType(B);
+
+    var C = _class(name: 'C', interfaces: [typeA]);
+    var typeC = _interfaceType(C);
+
+    var D = _class(name: 'D', interfaces: [typeC]);
+    var typeD = _interfaceType(D);
+
     _checkLeastUpperBound(typeB, typeD, typeA);
   }
 
   void test_sharedSuperinterface3() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    ClassElementImpl classC = ElementFactory.classElement2("C");
-    ClassElementImpl classD = ElementFactory.classElement2("D");
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
-    InterfaceType typeD = classD.type;
-    classB.interfaces = <InterfaceType>[typeA];
-    classC.interfaces = <InterfaceType>[typeB];
-    classD.interfaces = <InterfaceType>[typeB];
+    var A = _class(name: 'A');
+    var typeA = _interfaceType(A);
+
+    var B = _class(name: 'B', interfaces: [typeA]);
+    var typeB = _interfaceType(B);
+
+    var C = _class(name: 'C', interfaces: [typeB]);
+    var typeC = _interfaceType(C);
+
+    var D = _class(name: 'D', interfaces: [typeB]);
+    var typeD = _interfaceType(D);
+
     _checkLeastUpperBound(typeC, typeD, typeB);
   }
 
   void test_sharedSuperinterface4() {
-    ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classA2 = ElementFactory.classElement2("A2");
-    ClassElement classA3 = ElementFactory.classElement2("A3");
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    ClassElementImpl classC = ElementFactory.classElement2("C");
-    InterfaceType typeA = classA.type;
-    InterfaceType typeA2 = classA2.type;
-    InterfaceType typeA3 = classA3.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
-    classB.interfaces = <InterfaceType>[typeA, typeA2];
-    classC.interfaces = <InterfaceType>[typeA, typeA3];
+    var A = _class(name: 'A');
+    var typeA = _interfaceType(A);
+
+    var A2 = _class(name: 'A2');
+    var typeA2 = _interfaceType(A2);
+
+    var A3 = _class(name: 'A3');
+    var typeA3 = _interfaceType(A3);
+
+    var B = _class(name: 'B', interfaces: [typeA, typeA2]);
+    var typeB = _interfaceType(B);
+
+    var C = _class(name: 'C', interfaces: [typeA, typeA3]);
+    var typeC = _interfaceType(C);
+
     _checkLeastUpperBound(typeB, typeC, typeA);
   }
 
@@ -2285,82 +2578,90 @@
   }
 
   void test_typeParam_boundedByParam() {
-    TypeParameterElementImpl typeParamElementT =
-        ElementFactory.typeParameterElement('T');
-    TypeParameterElementImpl typeParamElementS =
-        ElementFactory.typeParameterElement('S');
-    DartType typeParamT = typeParamElementT.type;
-    DartType typeParamS = typeParamElementS.type;
-    typeParamElementT.bound = typeParamS;
-    _checkLeastUpperBound(typeParamT, typeParamS, typeParamS);
+    var S = _typeParameter('S');
+    var typeS = _typeParameterType(S);
+
+    var T = _typeParameter('T', bound: typeS);
+    var typeT = _typeParameterType(T);
+
+    _checkLeastUpperBound(typeT, typeS, typeS);
   }
 
   void test_typeParam_class_implements_Function_ignored() {
-    DartType typeA = ElementFactory.classElement('A', functionType).type;
-    TypeParameterElementImpl typeParamElement =
-        ElementFactory.typeParameterElement('T');
-    typeParamElement.bound = typeA;
-    DartType typeParam = typeParamElement.type;
-    _checkLeastUpperBound(typeParam, simpleFunctionType, objectType);
+    var A = _class(name: 'A', superType: functionType);
+    var T = _typeParameter('T', bound: _interfaceType(A));
+    _checkLeastUpperBound(_typeParameterType(T), _functionType(), objectType);
   }
 
   void test_typeParam_fBounded() {
-    ClassElementImpl AClass = ElementFactory.classElement2('A', ["Q"]);
-    InterfaceType AType = AClass.type;
+    var T = _typeParameter('Q');
+    var A = _class(name: 'A', typeParameters: [T]);
 
-    DartType s = TypeBuilder.variable("S");
-    (s.element as TypeParameterElementImpl).bound = AType.instantiate([s]);
-    DartType u = TypeBuilder.variable("U");
-    (u.element as TypeParameterElementImpl).bound = AType.instantiate([u]);
+    var S = _typeParameter('S');
+    var typeS = _typeParameterType(S);
+    S.bound = _interfaceType(A, typeArguments: [typeS]);
 
-    _checkLeastUpperBound(s, u, AType.instantiate([objectType]));
+    var U = _typeParameter('U');
+    var typeU = _typeParameterType(U);
+    U.bound = _interfaceType(A, typeArguments: [typeU]);
+
+    _checkLeastUpperBound(
+      typeS,
+      _typeParameterType(U),
+      _interfaceType(A, typeArguments: [objectType]),
+    );
   }
 
   void test_typeParam_function_bounded() {
-    TypeParameterElementImpl typeParamElement =
-        ElementFactory.typeParameterElement('T');
-    typeParamElement.bound = functionType;
-    DartType typeParam = typeParamElement.type;
-    _checkLeastUpperBound(typeParam, simpleFunctionType, functionType);
+    var T = _typeParameter('T', bound: functionType);
+    _checkLeastUpperBound(_typeParameterType(T), _functionType(), functionType);
   }
 
   void test_typeParam_function_noBound() {
-    DartType typeParam = ElementFactory.typeParameterElement('T').type;
-    _checkLeastUpperBound(typeParam, simpleFunctionType, objectType);
+    var T = _typeParameter('T');
+    _checkLeastUpperBound(_typeParameterType(T), _functionType(), objectType);
   }
 
   void test_typeParam_interface_bounded() {
-    DartType typeA = ElementFactory.classElement2('A', []).type;
-    DartType typeB = ElementFactory.classElement('B', typeA).type;
-    DartType typeC = ElementFactory.classElement('C', typeA).type;
-    TypeParameterElementImpl typeParamElement =
-        ElementFactory.typeParameterElement('T');
-    typeParamElement.bound = typeB;
-    DartType typeParam = typeParamElement.type;
-    _checkLeastUpperBound(typeParam, typeC, typeA);
+    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 T = _typeParameter('T', bound: typeB);
+    var typeT = _typeParameterType(T);
+
+    _checkLeastUpperBound(typeT, typeC, typeA);
   }
 
   void test_typeParam_interface_noBound() {
-    DartType typeParam = ElementFactory.typeParameterElement('T').type;
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
-    _checkLeastUpperBound(typeParam, interfaceType, objectType);
+    var T = _typeParameter('T');
+    var A = _class(name: 'A');
+    _checkLeastUpperBound(
+      _typeParameterType(T),
+      _interfaceType(A),
+      objectType,
+    );
   }
 
   /// Check least upper bound of the same class with different type parameters.
   void test_typeParameters_different() {
     // class List<int>
     // class List<double>
-    InterfaceType listOfIntType = listType.instantiate(<DartType>[intType]);
-    InterfaceType listOfDoubleType =
-        listType.instantiate(<DartType>[doubleType]);
-    InterfaceType listOfNum = listType.instantiate(<DartType>[numType]);
+    var listOfIntType = listType(intType);
+    var listOfDoubleType = listType(doubleType);
+    var listOfNum = listType(numType);
     _checkLeastUpperBound(listOfIntType, listOfDoubleType, listOfNum);
   }
 
   void test_typeParameters_same() {
     // List<int>
     // List<int>
-    InterfaceType listOfIntType = listType.instantiate(<DartType>[intType]);
+    var listOfIntType = listType(intType);
     _checkLeastUpperBound(listOfIntType, listOfIntType, listOfIntType);
   }
 
@@ -2369,9 +2670,8 @@
   void test_typeParametersAndClass_different() {
     // class List<int>
     // class Iterable<double>
-    InterfaceType listOfIntType = listType.instantiate(<DartType>[intType]);
-    InterfaceType iterableOfDoubleType =
-        iterableType.instantiate(<DartType>[doubleType]);
+    var listOfIntType = listType(intType);
+    var iterableOfDoubleType = iterableType(doubleType);
     // TODO(leafp): this should be iterableOfNumType
     _checkLeastUpperBound(listOfIntType, iterableOfDoubleType, objectType);
   }
@@ -2379,9 +2679,9 @@
   void test_void() {
     List<DartType> types = [
       bottomType,
-      simpleFunctionType,
-      ElementFactory.classElement2('A', []).type,
-      ElementFactory.typeParameterElement('T').type
+      _functionType(),
+      _interfaceType(_class(name: 'A')),
+      _typeParameterType(_typeParameter('T')),
     ];
     for (DartType type in types) {
       _checkLeastUpperBound(
@@ -2396,24 +2696,9 @@
 @reflectiveTest
 class NonNullableSubtypingTest extends SubtypingTestBase {
   @override
-  void setUp() {
-    typeProvider = TestAnalysisContext(
-      featureSet: FeatureSet.forTesting(
-        additionalFeatures: [Feature.non_nullable],
-      ),
-    ).typeProvider;
-
-    // TypeSystem should use the context type provider.
-    typeSystem = new Dart2TypeSystem(typeProvider);
-
-    LibraryElement coreLibrary = typeProvider.objectType.element.library;
-    LibraryElement asyncLibrary = typeProvider.streamType.element.library;
-
-    // Get a non-nullable type provider for convience during the test.
-    typeProvider = TypeProviderImpl(
-      coreLibrary,
-      asyncLibrary,
-      nullabilitySuffix: NullabilitySuffix.none,
+  FeatureSet get testFeatureSet {
+    return FeatureSet.forTesting(
+      additionalFeatures: [Feature.non_nullable],
     );
   }
 
@@ -2433,9 +2718,9 @@
         (objectType as TypeImpl).withNullability(NullabilitySuffix.star);
     var objectQuestion =
         (objectType as TypeImpl).withNullability(NullabilitySuffix.question);
-    var futureOrObject = futureOrType.instantiate([objectType]);
-    var futureOrObjectStar = futureOrType.instantiate([objectStar]);
-    var futureOrObjectQuestion = futureOrType.instantiate([objectQuestion]);
+    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)
@@ -2463,7 +2748,7 @@
       futureOrQuestionObject,
       futureOrQuestionObjectStar,
       futureOrStarObjectQuestion,
-      futureOrQuestionObjectQuestion
+      futureOrQuestionObjectQuestion,
     ]);
   }
 
@@ -2571,7 +2856,7 @@
       doubleType,
       intType,
       numType,
-      objectType
+      objectType,
     ];
 
     for (final formOfNull in equivalents) {
@@ -2597,7 +2882,7 @@
       _question(doubleType),
       _question(numType),
       _question(intType),
-      nullType
+      nullType,
     ];
     _checkGroups(objectType,
         equivalents: equivalents,
@@ -2616,7 +2901,7 @@
 @reflectiveTest
 class SubtypingTest extends SubtypingTestBase {
   void test_bottom_isBottom() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    var A = _class(name: 'A');
     List<DartType> equivalents = <DartType>[bottomType];
     List<DartType> supertypes = <DartType>[
       dynamicType,
@@ -2626,36 +2911,42 @@
       numType,
       stringType,
       functionType,
-      interfaceType
+      _interfaceType(A),
     ];
     _checkGroups(bottomType, equivalents: equivalents, supertypes: supertypes);
   }
 
   void test_call_method() {
-    ClassElementImpl classBottom = ElementFactory.classElement2("Bottom");
-    MethodElement methodBottom =
-        ElementFactory.methodElement("call", objectType, <DartType>[intType]);
-    classBottom.methods = <MethodElement>[methodBottom];
+    var A = _class(name: 'A', methods: [
+      _method('call', objectType, parameters: [
+        _requiredParameter('_', intType),
+      ]),
+    ]);
 
-    DartType top =
-        TypeBuilder.function(required: <DartType>[intType], result: objectType);
-    InterfaceType bottom = classBottom.type;
-
-    _checkIsNotSubtypeOf(bottom, top);
+    _checkIsNotSubtypeOf(
+      _interfaceType(A),
+      _functionType(required: [intType], returns: objectType),
+    );
   }
 
   void test_classes() {
-    ClassElement classTop = ElementFactory.classElement2("A");
-    ClassElement classLeft = ElementFactory.classElement("B", classTop.type);
-    ClassElement classRight = ElementFactory.classElement("C", classTop.type);
-    ClassElement classBottom = ElementFactory.classElement("D", classLeft.type)
-      ..interfaces = <InterfaceType>[classRight.type];
-    InterfaceType top = classTop.type;
-    InterfaceType left = classLeft.type;
-    InterfaceType right = classRight.type;
-    InterfaceType bottom = classBottom.type;
+    var A = _class(name: 'A');
+    var typeA = _interfaceType(A);
 
-    _checkLattice(top, left, right, bottom);
+    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() {
@@ -2667,7 +2958,7 @@
   }
 
   void test_dynamic_isTop() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    var A = _class(name: 'A');
     List<DartType> equivalents = <DartType>[dynamicType, objectType, voidType];
     List<DartType> subtypes = <DartType>[
       intType,
@@ -2675,8 +2966,8 @@
       numType,
       stringType,
       functionType,
-      interfaceType,
-      bottomType
+      _interfaceType(A),
+      bottomType,
     ];
     _checkGroups(dynamicType, equivalents: equivalents, subtypes: subtypes);
   }
@@ -2684,10 +2975,9 @@
   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.instantiate([t])).toList());
+    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.instantiate([t])).toList());
+    tops.addAll(tops.skip(3).map((t) => futureOrType(t)).toList());
 
     // Function should subtype all of those top types.
     _checkGroups(functionType, supertypes: [
@@ -2697,106 +2987,187 @@
     ]);
 
     // Create a non-identical but equal copy of Function, and verify subtyping
-    var copyOfFunction = new InterfaceTypeImpl(functionType.element);
+    var copyOfFunction = _interfaceType(functionType.element);
     _checkEquivalent(functionType, copyOfFunction);
   }
 
   void test_genericFunction_generic_monomorphic() {
-    DartType s = TypeBuilder.variable("S");
-    DartType t = TypeBuilder.variable("T", bound: s);
-    DartType u = TypeBuilder.variable("U", bound: intType);
-    DartType v = TypeBuilder.variable("V", bound: u);
+    var S = _typeParameter('S');
+    var T = _typeParameter('T', bound: _typeParameterType(S));
+    var U = _typeParameter('U', bound: intType);
+    var V = _typeParameter('V', bound: _typeParameterType(U));
 
-    DartType a = TypeBuilder.variable("A");
-    DartType b = TypeBuilder.variable("B", bound: a);
-    DartType c = TypeBuilder.variable("C", bound: intType);
-    DartType d = TypeBuilder.variable("D", bound: c);
+    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(
-        TypeBuilder.function(types: [s, t], required: [s], result: t),
-        TypeBuilder.function(
-            types: [a, b], required: [bottomType], result: dynamicType));
+      _functionType(
+        typeFormals: [S, T],
+        required: [_typeParameterType(S)],
+        returns: _typeParameterType(T),
+      ),
+      _functionType(
+        typeFormals: [A, B],
+        required: [bottomType],
+        returns: dynamicType,
+      ),
+    );
 
     _checkIsNotSubtypeOf(
-        TypeBuilder.function(types: [u, v], required: [u], result: v),
-        TypeBuilder.function(
-            types: [c, d], required: [objectType], result: objectType));
+      _functionType(
+        typeFormals: [U, V],
+        required: [_typeParameterType(U)],
+        returns: _typeParameterType(V),
+      ),
+      _functionType(
+        typeFormals: [C, D],
+        required: [objectType],
+        returns: objectType,
+      ),
+    );
 
     _checkIsNotSubtypeOf(
-        TypeBuilder.function(types: [u, v], required: [u], result: v),
-        TypeBuilder.function(
-            types: [c, d], required: [intType], result: intType));
+      _functionType(
+        typeFormals: [U, V],
+        required: [_typeParameterType(U)],
+        returns: _typeParameterType(V),
+      ),
+      _functionType(
+        typeFormals: [C, D],
+        required: [intType],
+        returns: intType,
+      ),
+    );
   }
 
   void test_genericFunction_genericDoesNotSubtypeNonGeneric() {
-    DartType s = TypeBuilder.variable("S");
-    DartType t = TypeBuilder.variable("T", bound: s);
-    DartType u = TypeBuilder.variable("U", bound: intType);
-    DartType v = TypeBuilder.variable("V", bound: u);
+    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(
-        TypeBuilder.function(types: [s, t], required: [s], result: t),
-        TypeBuilder.function(required: [dynamicType], result: dynamicType));
+      _functionType(
+        typeFormals: [S, T],
+        required: [_typeParameterType(S)],
+        returns: _typeParameterType(T),
+      ),
+      _functionType(required: [dynamicType], returns: dynamicType),
+    );
 
     _checkIsNotSubtypeOf(
-        TypeBuilder.function(types: [u, v], required: [u], result: v),
-        TypeBuilder.function(required: [objectType], result: objectType));
+      _functionType(
+        typeFormals: [U, V],
+        required: [_typeParameterType(U)],
+        returns: _typeParameterType(V),
+      ),
+      _functionType(required: [objectType], returns: objectType),
+    );
 
     _checkIsNotSubtypeOf(
-        TypeBuilder.function(types: [u, v], required: [u], result: v),
-        TypeBuilder.function(required: [intType], result: intType));
+      _functionType(
+        typeFormals: [U, V],
+        required: [_typeParameterType(U)],
+        returns: _typeParameterType(V),
+      ),
+      _functionType(required: [intType], returns: intType),
+    );
   }
 
   void test_genericFunction_simple() {
-    DartType s = TypeBuilder.variable("S");
-    DartType t = TypeBuilder.variable("T");
+    var S = _typeParameter('S');
+    var T = _typeParameter('T');
 
     _checkEquivalent(
-        TypeBuilder.function(types: [t]), TypeBuilder.function(types: [s]));
+      _functionType(typeFormals: [T]),
+      _functionType(typeFormals: [S]),
+    );
 
-    _checkEquivalent(TypeBuilder.function(types: [t], required: [t], result: t),
-        TypeBuilder.function(types: [s], required: [s], result: 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() {
-    DartType s = TypeBuilder.variable("S");
-    DartType t = TypeBuilder.variable("T", bound: s);
-    DartType u = TypeBuilder.variable("U");
-    DartType v = TypeBuilder.variable("V", bound: u);
-
-    _checkEquivalent(TypeBuilder.function(types: [s, t]),
-        TypeBuilder.function(types: [u, v]));
+    var S = _typeParameter('S');
+    var T = _typeParameter('T', bound: _typeParameterType(S));
+    var U = _typeParameter('U');
+    var V = _typeParameter('V', bound: _typeParameterType(U));
 
     _checkEquivalent(
-        TypeBuilder.function(types: [s, t], required: [s], result: t),
-        TypeBuilder.function(types: [u, v], required: [u], result: v));
+      _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),
+      ),
+    );
 
     {
-      DartType top =
-          TypeBuilder.function(types: [s, t], required: [t], result: s);
-      DartType left =
-          TypeBuilder.function(types: [u, v], required: [u], result: u);
-      DartType right =
-          TypeBuilder.function(types: [u, v], required: [v], result: v);
-      DartType bottom =
-          TypeBuilder.function(types: [s, t], required: [s], result: t);
+      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() {
-    ClassElementImpl LClass = ElementFactory.classElement2('L', ["T"]);
-    InterfaceType LType = LClass.type;
-    ClassElementImpl MClass = ElementFactory.classElement2('M', ["T"]);
-    DartType typeParam = MClass.typeParameters[0].type;
-    InterfaceType superType = LType.instantiate(<DartType>[typeParam]);
-    MClass.interfaces = <InterfaceType>[superType];
-    InterfaceType MType = MClass.type;
+    var LT = _typeParameter('T');
+    var L = _class(name: 'L', typeParameters: [LT]);
 
-    InterfaceType top = LType.instantiate(<DartType>[dynamicType]);
-    InterfaceType left = MType.instantiate(<DartType>[dynamicType]);
-    InterfaceType right = LType.instantiate(<DartType>[intType]);
-    InterfaceType bottom = MType.instantiate(<DartType>[intType]);
+    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);
   }
@@ -2810,36 +3181,36 @@
   }
 
   void test_named_optional() {
-    DartType r =
-        TypeBuilder.function(required: <DartType>[intType], result: intType);
-    DartType o = TypeBuilder.function(
-        required: <DartType>[], optional: <DartType>[intType], result: intType);
-    DartType n = TypeBuilder.function(
-        required: <DartType>[],
-        named: <String, DartType>{'x': intType},
-        result: intType);
-    DartType rr = TypeBuilder.function(
-        required: <DartType>[intType, intType], result: intType);
-    DartType ro = TypeBuilder.function(
-        required: <DartType>[intType],
-        optional: <DartType>[intType],
-        result: intType);
-    DartType rn = TypeBuilder.function(
-        required: <DartType>[intType],
-        named: <String, DartType>{'x': intType},
-        result: intType);
-    DartType oo = TypeBuilder.function(
-        required: <DartType>[],
-        optional: <DartType>[intType, intType],
-        result: intType);
-    DartType nn = TypeBuilder.function(
-        required: <DartType>[],
-        named: <String, DartType>{'x': intType, 'y': intType},
-        result: intType);
-    DartType nnn = TypeBuilder.function(
-        required: <DartType>[],
-        named: <String, DartType>{'x': intType, 'y': intType, 'z': intType},
-        result: intType);
+    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],
@@ -2882,36 +3253,29 @@
   }
 
   void test_simple_function() {
-    FunctionType top =
-        TypeBuilder.function(required: <DartType>[intType], result: objectType);
-    FunctionType left =
-        TypeBuilder.function(required: <DartType>[intType], result: intType);
-    FunctionType right = TypeBuilder.function(
-        required: <DartType>[objectType], result: objectType);
-    FunctionType bottom =
-        TypeBuilder.function(required: <DartType>[objectType], result: intType);
+    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() {
-    FunctionType functionType =
-        TypeBuilder.function(required: <DartType>[intType], result: objectType);
+    var functionType = _functionType(required: [intType], returns: objectType);
     _checkIsNotSubtypeOf(voidType, functionType);
   }
 
   void test_void_functions() {
-    FunctionType top =
-        TypeBuilder.function(required: <DartType>[intType], result: voidType);
-    FunctionType bottom =
-        TypeBuilder.function(required: <DartType>[objectType], result: intType);
+    var top = _functionType(required: [intType], returns: voidType);
+    var bottom = _functionType(required: [objectType], returns: intType);
 
     _checkIsStrictSubtypeOf(bottom, top);
   }
 
   void test_void_isTop() {
-    DartType interfaceType = ElementFactory.classElement2('A', []).type;
+    var A = _class(name: 'A');
     List<DartType> equivalents = <DartType>[dynamicType, objectType, voidType];
     List<DartType> subtypes = <DartType>[
       intType,
@@ -2919,47 +3283,14 @@
       numType,
       stringType,
       functionType,
-      interfaceType,
+      _interfaceType(A),
       bottomType
     ];
     _checkGroups(voidType, equivalents: equivalents, subtypes: subtypes);
   }
 }
 
-class SubtypingTestBase {
-  TypeProvider typeProvider;
-  TypeSystem typeSystem;
-
-  DartType get bottomType => typeProvider.bottomType;
-
-  InterfaceType get doubleType => typeProvider.doubleType;
-
-  DartType get dynamicType => typeProvider.dynamicType;
-
-  InterfaceType get functionType => typeProvider.functionType;
-
-  InterfaceType get futureOrType => typeProvider.futureOrType;
-
-  InterfaceType get intType => typeProvider.intType;
-
-  InterfaceType get listType => typeProvider.listType;
-
-  DartType get nullType => typeProvider.nullType;
-
-  InterfaceType get numType => typeProvider.numType;
-
-  InterfaceType get objectType => typeProvider.objectType;
-
-  InterfaceType get stringType => typeProvider.stringType;
-
-  DartType get voidType => VoidTypeImpl.instance;
-
-  void setUp() {
-    var analysisContext = TestAnalysisContext();
-    typeProvider = analysisContext.typeProvider;
-    typeSystem = analysisContext.typeSystem;
-  }
-
+class SubtypingTestBase extends AbstractTypeSystemTest {
   void _checkEquivalent(DartType type1, DartType type2) {
     _checkIsSubtypeOf(type1, type2);
     _checkIsSubtypeOf(type2, type1);
@@ -3033,50 +3364,25 @@
   }
 }
 
-class TypeBuilder {
-  static FunctionTypeImpl function(
-      {List<DartType> types,
-      List<DartType> required,
-      List<DartType> optional,
-      Map<String, DartType> named,
-      DartType result}) {
-    result = result ?? VoidTypeImpl.instance;
-    required = required ?? [];
-    FunctionElementImpl f = ElementFactory.functionElement8(required, result,
-        optional: optional, named: named);
-    if (types != null) {
-      f.typeParameters =
-          new List<TypeParameterElement>.from(types.map((t) => t.element));
-    }
-    return f.type = new FunctionTypeImpl(f);
-  }
-
-  static TypeParameterType variable(String name, {DartType bound}) =>
-      ElementFactory.typeParameterWithType(name, bound).type;
-}
-
 @reflectiveTest
 class TypeSystemTest extends AbstractTypeSystemTest {
   InterfaceTypeImpl get functionClassTypeNone {
-    return InterfaceTypeImpl.explicit(
+    return _interfaceType(
       typeProvider.functionType.element,
-      const <DartType>[],
       nullabilitySuffix: NullabilitySuffix.none,
     );
   }
 
   InterfaceTypeImpl get functionClassTypeQuestion {
-    return InterfaceTypeImpl.explicit(
+    return _interfaceType(
       typeProvider.functionType.element,
-      const <DartType>[],
       nullabilitySuffix: NullabilitySuffix.question,
     );
   }
 
   InterfaceTypeImpl get functionClassTypeStar {
-    return InterfaceTypeImpl.explicit(
+    return _interfaceType(
       typeProvider.functionType.element,
-      const <DartType>[],
       nullabilitySuffix: NullabilitySuffix.star,
     );
   }
@@ -3085,28 +3391,22 @@
       .withNullability(NullabilitySuffix.none);
 
   FunctionTypeImpl get nothingToVoidFunctionTypeNone {
-    return FunctionTypeImpl.synthetic(
-      voidType,
-      const <TypeParameterElement>[],
-      const <ParameterElement>[],
+    return _functionType(
+      returns: voidType,
       nullabilitySuffix: NullabilitySuffix.none,
     );
   }
 
   FunctionTypeImpl get nothingToVoidFunctionTypeQuestion {
-    return FunctionTypeImpl.synthetic(
-      voidType,
-      const <TypeParameterElement>[],
-      const <ParameterElement>[],
+    return _functionType(
+      returns: voidType,
       nullabilitySuffix: NullabilitySuffix.question,
     );
   }
 
   FunctionTypeImpl get nothingToVoidFunctionTypeStar {
-    return FunctionTypeImpl.synthetic(
-      voidType,
-      const <TypeParameterElement>[],
-      const <ParameterElement>[],
+    return _functionType(
+      returns: voidType,
       nullabilitySuffix: NullabilitySuffix.star,
     );
   }
@@ -3127,79 +3427,76 @@
       .withNullability(NullabilitySuffix.star);
 
   InterfaceTypeImpl get stringClassTypeNone {
-    return InterfaceTypeImpl.explicit(
+    return _interfaceType(
       typeProvider.stringType.element,
-      const <DartType>[],
       nullabilitySuffix: NullabilitySuffix.none,
     );
   }
 
   InterfaceTypeImpl get stringClassTypeQuestion {
-    return InterfaceTypeImpl.explicit(
+    return _interfaceType(
       typeProvider.stringType.element,
-      const <DartType>[],
       nullabilitySuffix: NullabilitySuffix.question,
     );
   }
 
   InterfaceTypeImpl get stringClassTypeStar {
-    return InterfaceTypeImpl.explicit(
+    return _interfaceType(
       typeProvider.stringType.element,
-      const <DartType>[],
       nullabilitySuffix: NullabilitySuffix.star,
     );
   }
 
   InterfaceTypeImpl futureOrTypeNone({@required DartType argument}) {
-    var element = typeProvider.futureOrType.element;
-    return InterfaceTypeImpl.explicit(
+    var element = typeProvider.futureOrElement;
+    return _interfaceType(
       element,
-      <DartType>[argument],
+      typeArguments: <DartType>[argument],
       nullabilitySuffix: NullabilitySuffix.none,
     );
   }
 
   InterfaceTypeImpl futureOrTypeQuestion({@required DartType argument}) {
-    var element = typeProvider.futureOrType.element;
-    return InterfaceTypeImpl.explicit(
+    var element = typeProvider.futureOrElement;
+    return _interfaceType(
       element,
-      <DartType>[argument],
+      typeArguments: <DartType>[argument],
       nullabilitySuffix: NullabilitySuffix.question,
     );
   }
 
   InterfaceTypeImpl futureOrTypeStar({@required DartType argument}) {
-    var element = typeProvider.futureOrType.element;
-    return InterfaceTypeImpl.explicit(
+    var element = typeProvider.futureOrElement;
+    return _interfaceType(
       element,
-      <DartType>[argument],
+      typeArguments: <DartType>[argument],
       nullabilitySuffix: NullabilitySuffix.star,
     );
   }
 
   InterfaceTypeImpl listClassTypeNone(DartType argument) {
-    var element = typeProvider.listType.element;
-    return InterfaceTypeImpl.explicit(
+    var element = typeProvider.listElement;
+    return _interfaceType(
       element,
-      <DartType>[argument],
+      typeArguments: <DartType>[argument],
       nullabilitySuffix: NullabilitySuffix.none,
     );
   }
 
   InterfaceTypeImpl listClassTypeQuestion(DartType argument) {
-    var element = typeProvider.listType.element;
-    return InterfaceTypeImpl.explicit(
+    var element = typeProvider.listElement;
+    return _interfaceType(
       element,
-      <DartType>[argument],
+      typeArguments: <DartType>[argument],
       nullabilitySuffix: NullabilitySuffix.question,
     );
   }
 
   InterfaceTypeImpl listClassTypeStar(DartType argument) {
-    var element = typeProvider.listType.element;
-    return InterfaceTypeImpl.explicit(
+    var element = typeProvider.listElement;
+    return _interfaceType(
       element,
-      <DartType>[argument],
+      typeArguments: <DartType>[argument],
       nullabilitySuffix: NullabilitySuffix.star,
     );
   }
@@ -3808,27 +4105,24 @@
   }
 
   DartType typeParameterTypeNone({@required DartType bound}) {
-    var element = TypeParameterElementImpl.synthetic('T');
-    element.bound = bound;
-    return TypeParameterTypeImpl(
+    var element = _typeParameter('T', bound: bound);
+    return _typeParameterType(
       element,
       nullabilitySuffix: NullabilitySuffix.none,
     );
   }
 
   DartType typeParameterTypeQuestion({@required DartType bound}) {
-    var element = TypeParameterElementImpl.synthetic('T');
-    element.bound = bound;
-    return TypeParameterTypeImpl(
+    var element = _typeParameter('T', bound: bound);
+    return _typeParameterType(
       element,
       nullabilitySuffix: NullabilitySuffix.question,
     );
   }
 
   DartType typeParameterTypeStar({@required DartType bound}) {
-    var element = TypeParameterElementImpl.synthetic('T');
-    element.bound = bound;
-    return TypeParameterTypeImpl(
+    var element = _typeParameter('T', bound: bound);
+    return _typeParameterType(
       element,
       nullabilitySuffix: NullabilitySuffix.star,
     );
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 0d03acf..35828ff 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
@@ -22,6 +23,7 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../../generated/elements_types_mixin.dart';
 import '../../../utils.dart';
 import 'base.dart';
 
@@ -42,7 +44,8 @@
  * Integration tests for resolution.
  */
 @reflectiveTest
-class AnalysisDriverResolutionTest extends BaseAnalysisDriverTest {
+class AnalysisDriverResolutionTest extends BaseAnalysisDriverTest
+    with ElementsTypesMixin {
   ResolvedUnitResult result;
   FindNode findNode;
   FindElement findElement;
@@ -55,17 +58,15 @@
 
   DynamicTypeImpl get dynamicType => DynamicTypeImpl.instance;
 
-  ClassElement get futureElement => typeProvider.futureType.element;
+  ClassElement get futureElement => typeProvider.futureElement;
 
   ClassElement get intElement => typeProvider.intType.element;
 
   InterfaceType get intType => typeProvider.intType;
 
-  ClassElement get listElement => typeProvider.listType.element;
+  ClassElement get listElement => typeProvider.listElement;
 
-  ClassElement get mapElement => typeProvider.mapType.element;
-
-  InterfaceType get mapType => typeProvider.mapType;
+  ClassElement get mapElement => typeProvider.mapElement;
 
   ClassElement get numElement => typeProvider.numType.element;
 
@@ -716,7 +717,7 @@
     PrefixedIdentifier prefixed = annotation.name;
 
     expect(prefixed.prefix.staticElement, same(aClass));
-    expect(prefixed.prefix.staticType, aClass.type);
+    expect(prefixed.prefix.staticType, interfaceType(aClass));
 
     expect(prefixed.identifier.staticElement, same(aGetter));
     expect(prefixed.identifier.staticType, typeProvider.intType);
@@ -776,7 +777,7 @@
     PrefixedIdentifier prefixed = annotation.name;
 
     expect(prefixed.prefix.staticElement, same(aClass));
-    expect(prefixed.prefix.staticType, aClass.type);
+    expect(prefixed.prefix.staticType, interfaceType(aClass));
 
     expect(prefixed.identifier.staticElement, same(constructor));
     expect(
@@ -814,10 +815,10 @@
     expect(atD.element, constructorD);
 
     expect(constC.staticElement, constructorC);
-    expect(constC.staticType, elementC.type);
+    expect(constC.staticType, interfaceType(elementC));
 
     expect(constC.constructorName.staticElement, constructorC);
-    expect(constC.constructorName.type.type, elementC.type);
+    expect(constC.constructorName.type.type, interfaceType(elementC));
   }
 
   test_annotation_unprefixed_topLevelVariable() async {
@@ -1448,11 +1449,11 @@
       expect(constructorName.staticElement, same(aUnnamed));
 
       TypeName typeName = constructorName.type;
-      expect(typeName.type, aElement.type);
+      expect(typeName.type, interfaceType(aElement));
 
       SimpleIdentifier identifier = typeName.name;
       expect(identifier.staticElement, same(aElement));
-      expect(identifier.staticType, aElement.type);
+      expect(identifier.staticType, interfaceType(aElement));
 
       expect(constructorName.name, isNull);
     }
@@ -1468,11 +1469,11 @@
       expect(constructorName.staticElement, same(aNamed));
 
       TypeName typeName = constructorName.type;
-      expect(typeName.type, aElement.type);
+      expect(typeName.type, interfaceType(aElement));
 
       SimpleIdentifier identifier = typeName.name;
       expect(identifier.staticElement, same(aElement));
-      expect(identifier.staticType, aElement.type);
+      expect(identifier.staticType, interfaceType(aElement));
 
       expect(constructorName.name.staticElement, aNamed);
       expect(constructorName.name.staticType, isNull);
@@ -1497,8 +1498,12 @@
     ClassElement aElement = aNode.declaredElement;
 
     ClassDeclaration bNode = result.unit.declarations[1];
-    TypeParameterType uType = bNode.declaredElement.typeParameters[0].type;
-    InterfaceType auType = aElement.type.instantiate([uType]);
+    TypeParameterType uType =
+        typeParameterType(bNode.declaredElement.typeParameters[0]);
+    InterfaceType auType = aElement.instantiate(
+      typeArguments: [uType],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
 
     {
       ConstructorElement expectedElement = aElement.constructors[0];
@@ -1872,7 +1877,7 @@
     FieldDeclaration fDeclaration = cNode.members[0];
     VariableDeclaration fNode = fDeclaration.fields.variables[0];
     FieldElement fElement = fNode.declaredElement;
-    expect(fElement.type, typeProvider.listType.instantiate([tElement.type]));
+    expect(fElement.type, typeProvider.listType2(typeParameterType(tElement)));
   }
 
   test_field_generic() async {
@@ -2146,8 +2151,7 @@
 
     var typeProvider = unit.declaredElement.context.typeProvider;
     InterfaceType intType = typeProvider.intType;
-    InterfaceType listType = typeProvider.listType;
-    InterfaceType listIntType = listType.instantiate([intType]);
+    InterfaceType listIntType = typeProvider.listType2(intType);
 
     List<Statement> mainStatements = _getMainStatements(result);
 
@@ -2195,14 +2199,14 @@
       VariableDeclaration aNode = aDeclaration.variables.variables[0];
       InstanceCreationExpression value = aNode.initializer;
       expect(value.staticElement, defaultConstructor);
-      expect(value.staticType, cElement.type);
+      expect(value.staticType, interfaceType(cElement));
 
       TypeName typeName = value.constructorName.type;
       expect(typeName.typeArguments, isNull);
 
       Identifier typeIdentifier = typeName.name;
       expect(typeIdentifier.staticElement, cElement);
-      expect(typeIdentifier.staticType, cElement.type);
+      expect(typeIdentifier.staticType, interfaceType(cElement));
 
       expect(value.constructorName.name, isNull);
     }
@@ -2212,14 +2216,14 @@
       VariableDeclaration bNode = bDeclaration.variables.variables[0];
       InstanceCreationExpression value = bNode.initializer;
       expect(value.staticElement, namedConstructor);
-      expect(value.staticType, cElement.type);
+      expect(value.staticType, interfaceType(cElement));
 
       TypeName typeName = value.constructorName.type;
       expect(typeName.typeArguments, isNull);
 
       SimpleIdentifier typeIdentifier = typeName.name;
       expect(typeIdentifier.staticElement, cElement);
-      expect(typeIdentifier.staticType, cElement.type);
+      expect(typeIdentifier.staticType, interfaceType(cElement));
 
       SimpleIdentifier constructorName = value.constructorName.name;
       expect(constructorName.staticElement, namedConstructor);
@@ -2248,14 +2252,14 @@
     InstanceCreationExpression creation = vNode.initializer;
     List<Expression> arguments = creation.argumentList.arguments;
     expect(creation.staticElement, constructorElement);
-    expect(creation.staticType, xElement.type);
+    expect(creation.staticType, interfaceType(xElement));
 
     TypeName typeName = creation.constructorName.type;
     expect(typeName.typeArguments, isNull);
 
     Identifier typeIdentifier = typeName.name;
     expect(typeIdentifier.staticElement, xElement);
-    expect(typeIdentifier.staticType, xElement.type);
+    expect(typeIdentifier.staticType, interfaceType(xElement));
 
     expect(creation.constructorName.name, isNull);
 
@@ -2288,14 +2292,14 @@
       VariableDeclaration aNode = aDeclaration.variables.variables[0];
       InstanceCreationExpression value = aNode.initializer;
       expect(value.staticElement, defaultConstructor);
-      expect(value.staticType, cElement.type);
+      expect(value.staticType, interfaceType(cElement));
 
       TypeName typeName = value.constructorName.type;
       expect(typeName.typeArguments, isNull);
 
       Identifier typeIdentifier = typeName.name;
       expect(typeIdentifier.staticElement, cElement);
-      expect(typeIdentifier.staticType, cElement.type);
+      expect(typeIdentifier.staticType, interfaceType(cElement));
 
       expect(value.constructorName.name, isNull);
 
@@ -2308,14 +2312,14 @@
       VariableDeclaration bNode = bDeclaration.variables.variables[0];
       InstanceCreationExpression value = bNode.initializer;
       expect(value.staticElement, namedConstructor);
-      expect(value.staticType, cElement.type);
+      expect(value.staticType, interfaceType(cElement));
 
       TypeName typeName = value.constructorName.type;
       expect(typeName.typeArguments, isNull);
 
       SimpleIdentifier typeIdentifier = typeName.name;
       expect(typeIdentifier.staticElement, cElement);
-      expect(typeIdentifier.staticType, cElement.type);
+      expect(typeIdentifier.staticType, interfaceType(cElement));
 
       SimpleIdentifier constructorName = value.constructorName.name;
       expect(constructorName.staticElement, namedConstructor);
@@ -2351,12 +2355,17 @@
     ClassElement cElement = aLibrary.getType('C');
     ConstructorElement defaultConstructor = cElement.constructors[0];
     ConstructorElement namedConstructor = cElement.constructors[1];
-    InterfaceType cType = cElement.type;
-    var cTypeDynamic = cType.instantiate([DynamicTypeImpl.instance]);
+    InterfaceType cTypeDynamic = cElement.instantiate(
+      typeArguments: [DynamicTypeImpl.instance],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
 
     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;
@@ -2381,7 +2390,10 @@
     }
 
     {
-      var cTypeDouble = cType.instantiate([typeProvider.doubleType]);
+      var cTypeDouble = cElement.instantiate(
+        typeArguments: [typeProvider.doubleType],
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
 
       ExpressionStatement statement = statements[1];
       InstanceCreationExpression creation = statement.expression;
@@ -2408,7 +2420,10 @@
     }
 
     {
-      var cTypeBool = cType.instantiate([typeProvider.boolType]);
+      var cTypeBool = cElement.instantiate(
+        typeArguments: [typeProvider.boolType],
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
 
       ExpressionStatement statement = statements[2];
       InstanceCreationExpression creation = statement.expression;
@@ -2460,7 +2475,7 @@
     ClassElement cElement = unitElement.getType('C');
     ConstructorElement defaultConstructor = cElement.constructors[0];
     ConstructorElement namedConstructor = cElement.constructors[1];
-    InterfaceType cType = cElement.type;
+    InterfaceType cType = interfaceType(cElement);
 
     var statements = _getMainStatements(result);
     {
@@ -4161,7 +4176,7 @@
 
     TypeName fReturnTypeNode = fNode.returnType;
     expect(fReturnTypeNode.name.staticElement, same(tElement));
-    expect(fReturnTypeNode.type, tElement.type);
+    expect(fReturnTypeNode.type, typeParameterType(tElement));
 
     expect(fExpression.declaredElement, same(fElement));
 
@@ -4176,13 +4191,13 @@
           name: 'a',
           offset: 28,
           kind: ParameterKind.REQUIRED,
-          type: tElement.type);
+          type: typeParameterType(tElement));
 
       _assertSimpleParameter(nodes[1], parameters[1],
           name: 'b',
           offset: 33,
           kind: ParameterKind.REQUIRED,
-          type: uElement.type);
+          type: typeParameterType(uElement));
 
       var aRef = findNode.simple('a;');
       assertElement(aRef, parameters[0]);
@@ -5209,10 +5224,8 @@
     {
       ExpressionStatement statement = statements[0];
       SetOrMapLiteral mapLiteral = statement.expression;
-      expect(
-          mapLiteral.staticType,
-          typeProvider.mapType
-              .instantiate([typeProvider.intType, typeProvider.doubleType]));
+      expect(mapLiteral.staticType,
+          typeProvider.mapType2(typeProvider.intType, typeProvider.doubleType));
     }
 
     {
@@ -5220,8 +5233,8 @@
       SetOrMapLiteral mapLiteral = statement.expression;
       expect(
           mapLiteral.staticType,
-          typeProvider.mapType
-              .instantiate([typeProvider.boolType, typeProvider.stringType]));
+          typeProvider.mapType2(
+              typeProvider.boolType, typeProvider.stringType));
     }
   }
 
@@ -5722,7 +5735,7 @@
 
       SimpleIdentifier target = invocation.target;
       expect(target.staticElement, same(cElement));
-      expect(target.staticType, same(cElement.type));
+      expect(target.staticType, interfaceType(cElement));
 
       var invokeTypeStr = 'void Function(int)';
       expect(invocation.staticType.toString(), 'void');
@@ -6376,7 +6389,7 @@
 
     SimpleIdentifier prefix = prefixed.prefix;
     expect(prefix.staticElement, same(vElement));
-    expect(prefix.staticType, cElement.type);
+    expect(prefix.staticType, interfaceType(cElement));
 
     SimpleIdentifier identifier = prefixed.identifier;
     expect(identifier.staticElement, same(fElement.getter));
@@ -6407,7 +6420,7 @@
 
     SimpleIdentifier prefix = prefixed.prefix;
     expect(prefix.staticElement, same(cElement));
-    expect(prefix.staticType, cElement.type);
+    expect(prefix.staticType, interfaceType(cElement));
 
     SimpleIdentifier identifier = prefixed.identifier;
     expect(identifier.staticElement, same(fElement.getter));
@@ -6704,7 +6717,7 @@
 
       InstanceCreationExpression newC = access.target;
       expect(newC.staticElement, cClassElement.unnamedConstructor);
-      expect(newC.staticType, cClassElement.type);
+      expect(newC.staticType, interfaceType(cClassElement));
 
       expect(access.propertyName.staticElement, same(fElement.getter));
       expect(access.propertyName.staticType, typeProvider.intType);
@@ -6739,7 +6752,7 @@
 
       InstanceCreationExpression newC = access.target;
       expect(newC.staticElement, cClassElement.unnamedConstructor);
-      expect(newC.staticType, cClassElement.type);
+      expect(newC.staticType, interfaceType(cClassElement));
 
       expect(access.propertyName.staticElement, same(fElement.getter));
       expect(access.propertyName.staticType, typeProvider.intType);
@@ -6905,7 +6918,7 @@
       MethodInvocation invocation = statement.expression;
 
       SuperExpression target = invocation.target;
-      expect(target.staticType, bNode.declaredElement.type); // raw
+      expect(target.staticType, interfaceType(bNode.declaredElement)); // raw
 
       expect(invocation.methodName.staticElement, same(methodElement));
     }
@@ -6926,7 +6939,7 @@
       expect(propertyAccess.staticType, typeProvider.intType);
 
       SuperExpression target = propertyAccess.target;
-      expect(target.staticType, bNode.declaredElement.type); // raw
+      expect(target.staticType, interfaceType(bNode.declaredElement)); // raw
 
       expect(propertyAccess.propertyName.staticElement, same(getterElement));
       expect(propertyAccess.propertyName.staticType, typeProvider.intType);
@@ -6950,7 +6963,7 @@
       PropertyAccess propertyAccess = assignment.leftHandSide;
 
       SuperExpression target = propertyAccess.target;
-      expect(target.staticType, bNode.declaredElement.type); // raw
+      expect(target.staticType, interfaceType(bNode.declaredElement)); // raw
 
       expect(propertyAccess.propertyName.staticElement, same(setterElement));
       expect(propertyAccess.propertyName.staticType, typeProvider.intType);
@@ -6962,7 +6975,7 @@
       BinaryExpression binary = statement.expression;
 
       ThisExpression target = binary.leftOperand;
-      expect(target.staticType, bNode.declaredElement.type); // raw
+      expect(target.staticType, interfaceType(bNode.declaredElement)); // raw
 
       expect(binary.staticElement, same(operatorElement));
       expect(binary.staticType, typeProvider.intType);
@@ -7001,6 +7014,9 @@
     BlockFunctionBody testBody = testNode.body;
     List<Statement> testStatements = testBody.block.statements;
 
+    var elementA = findElement.class_('A');
+    var thisTypeA = interfaceType(elementA);
+
     // method(1);
     {
       ExpressionStatement statement = testStatements[0];
@@ -7017,7 +7033,7 @@
       MethodInvocation invocation = statement.expression;
 
       ThisExpression target = invocation.target;
-      expect(target.staticType, aNode.declaredElement.type); // raw
+      expect(target.staticType, thisTypeA); // raw
 
       expect(invocation.methodName.staticElement, same(methodElement));
     }
@@ -7038,7 +7054,7 @@
       expect(propertyAccess.staticType, typeProvider.intType);
 
       ThisExpression target = propertyAccess.target;
-      expect(target.staticType, aNode.declaredElement.type); // raw
+      expect(target.staticType, thisTypeA); // raw
 
       expect(propertyAccess.propertyName.staticElement, same(getterElement));
       expect(propertyAccess.propertyName.staticType, typeProvider.intType);
@@ -7062,7 +7078,7 @@
       PropertyAccess propertyAccess = assignment.leftHandSide;
 
       ThisExpression target = propertyAccess.target;
-      expect(target.staticType, aNode.declaredElement.type); // raw
+      expect(target.staticType, thisTypeA); // raw
 
       expect(propertyAccess.propertyName.staticElement, same(setterElement));
       expect(propertyAccess.propertyName.staticType, typeProvider.intType);
@@ -7074,7 +7090,7 @@
       BinaryExpression binary = statement.expression;
 
       ThisExpression target = binary.leftOperand;
-      expect(target.staticType, aNode.declaredElement.type); // raw
+      expect(target.staticType, thisTypeA); // raw
 
       expect(binary.staticElement, same(operatorElement));
       expect(binary.staticType, typeProvider.intType);
@@ -7152,8 +7168,10 @@
     expect(dName.staticType, typeProvider.typeType);
 
     {
-      var aRawType = aElement.type;
-      var expectedType = aRawType.instantiate([typeProvider.boolType]);
+      var expectedType = aElement.instantiate(
+        typeArguments: [typeProvider.boolType],
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
 
       TypeName superClass = dNode.extendsClause.superclass;
       expect(superClass.type, expectedType);
@@ -7164,8 +7182,10 @@
     }
 
     {
-      var bRawType = bElement.type;
-      var expectedType = bRawType.instantiate([typeProvider.intType]);
+      var expectedType = bElement.instantiate(
+        typeArguments: [typeProvider.intType],
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
 
       TypeName mixinType = dNode.withClause.mixinTypes[0];
       expect(mixinType.type, expectedType);
@@ -7176,8 +7196,10 @@
     }
 
     {
-      var cRawType = cElement.type;
-      var expectedType = cRawType.instantiate([typeProvider.doubleType]);
+      var expectedType = cElement.instantiate(
+        typeArguments: [typeProvider.doubleType],
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
 
       TypeName implementedType = dNode.implementsClause.interfaces[0];
       expect(implementedType.type, expectedType);
@@ -7215,8 +7237,10 @@
     expect(dName.staticType, typeProvider.typeType);
 
     {
-      var aRawType = aElement.type;
-      var expectedType = aRawType.instantiate([typeProvider.boolType]);
+      var expectedType = aElement.instantiate(
+        typeArguments: [typeProvider.boolType],
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
 
       TypeName superClass = dNode.superclass;
       expect(superClass.type, expectedType);
@@ -7227,8 +7251,10 @@
     }
 
     {
-      var bRawType = bElement.type;
-      var expectedType = bRawType.instantiate([typeProvider.intType]);
+      var expectedType = bElement.instantiate(
+        typeArguments: [typeProvider.intType],
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
 
       TypeName mixinType = dNode.withClause.mixinTypes[0];
       expect(mixinType.type, expectedType);
@@ -7239,8 +7265,10 @@
     }
 
     {
-      var cRawType = cElement.type;
-      var expectedType = cRawType.instantiate([typeProvider.doubleType]);
+      var expectedType = cElement.instantiate(
+        typeArguments: [typeProvider.doubleType],
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
 
       TypeName interfaceType = dNode.implementsClause.interfaces[0];
       expect(interfaceType.type, expectedType);
@@ -7272,7 +7300,7 @@
       var aNode = enumNode.constants[0];
       expect(aNode.declaredElement, same(aElement));
       expect(aNode.name.staticElement, same(aElement));
-      expect(aNode.name.staticType, same(enumElement.type));
+      expect(aNode.name.staticType, interfaceType(enumElement));
     }
 
     {
@@ -7280,7 +7308,7 @@
       var bNode = enumNode.constants[1];
       expect(bNode.declaredElement, same(bElement));
       expect(bNode.name.staticElement, same(bElement));
-      expect(bNode.name.staticType, same(enumElement.type));
+      expect(bNode.name.staticType, interfaceType(enumElement));
     }
   }
 
@@ -7557,11 +7585,11 @@
       TypeName typeName = bDeclaration.fields.type;
       SimpleIdentifier typeIdentifier = typeName.name;
       expect(typeIdentifier.staticElement, same(tElement));
-      expect(typeIdentifier.staticType, tElement.type);
+      expect(typeIdentifier.staticType, typeParameterType(tElement));
 
       VariableDeclaration bNode = bDeclaration.fields.variables[0];
       expect(bNode.declaredElement, same(bElement));
-      expect(bElement.type, tElement.type);
+      expect(bElement.type, typeParameterType(tElement));
       expect(bNode.name.staticElement, same(bElement));
       expect(bNode.name.staticType, same(bElement.type));
     }
@@ -7803,7 +7831,7 @@
         name: 'b',
         offset: 27,
         kind: ParameterKind.REQUIRED,
-        type: aliasElement.typeParameters[0].type);
+        type: typeParameterType(aliasElement.typeParameters[0]));
   }
 
   test_top_typeParameter() async {
@@ -7830,16 +7858,19 @@
       expect(tNode.declaredElement, same(cElement.typeParameters[0]));
 
       TypeName bound = tNode.bound;
-      expect(bound.type, aElement.type);
+      expect(bound.type, interfaceType(aElement));
 
       SimpleIdentifier boundIdentifier = bound.name;
       expect(boundIdentifier.staticElement, same(aElement));
-      expect(boundIdentifier.staticType, aElement.type);
+      expect(boundIdentifier.staticType, interfaceType(aElement));
     }
 
     {
-      var listElement = typeProvider.listType.element;
-      var listOfA = typeProvider.listType.instantiate([aElement.type]);
+      var listElement = typeProvider.listElement;
+      var listOfA = listElement.instantiate(
+        typeArguments: [interfaceType(aElement)],
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
 
       TypeParameter uNode = cNode.typeParameters.typeParameters[1];
       expect(uNode.declaredElement, same(cElement.typeParameters[1]));
@@ -7852,11 +7883,11 @@
       expect(listIdentifier.staticType, listOfA);
 
       TypeName aTypeName = bound.typeArguments.arguments[0];
-      expect(aTypeName.type, aElement.type);
+      expect(aTypeName.type, interfaceType(aElement));
 
       SimpleIdentifier aIdentifier = aTypeName.name;
       expect(aIdentifier.staticElement, same(aElement));
-      expect(aIdentifier.staticType, aElement.type);
+      expect(aIdentifier.staticType, interfaceType(aElement));
     }
 
     {
@@ -8358,7 +8389,7 @@
     ExpressionStatement statement = statements[0];
 
     InstanceCreationExpression creation = statement.expression;
-    expect(creation.staticType, randomElement.type);
+    expect(creation.staticType, interfaceType(randomElement));
 
     ConstructorName constructorName = creation.constructorName;
 
@@ -8901,8 +8932,6 @@
     }
     fail('Not found $name');
   }
-
-//  String _p(String path) => convertPath(path);
 }
 
 /**
diff --git a/pkg/analyzer/test/src/dart/analysis/index_test.dart b/pkg/analyzer/test/src/dart/analysis/index_test.dart
index 38f6ff8..c83c483 100644
--- a/pkg/analyzer/test/src/dart/analysis/index_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/index_test.dart
@@ -67,6 +67,19 @@
     return imports[index].importedLibrary.definingCompilationUnit;
   }
 
+  test_fieldFormalParameter_noSuchField() async {
+    await _indexTestUnit('''
+class B<T> {
+  B({this.x}) {}
+
+  foo() {
+    B<int>(x: 1);
+  }
+}
+''');
+    // No exceptions.
+  }
+
   test_hasAncestor_ClassDeclaration() async {
     await _indexTestUnit('''
 class A {}
diff --git a/pkg/analyzer/test/src/dart/ast/utilities_test.dart b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
index 0a8e03d..88f8e7a 100644
--- a/pkg/analyzer/test/src/dart/ast/utilities_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
@@ -11,12 +11,15 @@
 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';
+import 'package:analyzer/src/generated/testing/test_type_provider.dart';
 import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../../generated/elements_types_mixin.dart';
 import '../../../generated/parser_test.dart' show ParserTestCase;
 import '../../../generated/test_support.dart';
 import '../../../util/ast_type_matchers.dart';
@@ -130,7 +133,9 @@
 }
 
 @reflectiveTest
-class ResolutionCopierTest extends EngineTestCase {
+class ResolutionCopierTest with ElementsTypesMixin {
+  final TypeProvider typeProvider = TestTypeProvider();
+
   void test_visitAdjacentStrings() {
     AdjacentStrings createNode() => astFactory.adjacentStrings([
           astFactory.simpleStringLiteral(null, 'hello'),
@@ -138,7 +143,7 @@
         ]);
 
     AdjacentStrings fromNode = createNode();
-    DartType staticType = ElementFactory.classElement2("B").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('B'));
     fromNode.staticType = staticType;
 
     AdjacentStrings toNode = createNode();
@@ -161,7 +166,7 @@
   void test_visitAsExpression() {
     AsExpression fromNode = AstTestFactory.asExpression(
         AstTestFactory.identifier3("x"), AstTestFactory.typeName4("A"));
-    DartType staticType = ElementFactory.classElement2("B").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('B'));
     fromNode.staticType = staticType;
     AsExpression toNode = AstTestFactory.asExpression(
         AstTestFactory.identifier3("x"), AstTestFactory.typeName4("A"));
@@ -174,7 +179,7 @@
         AstTestFactory.identifier3("a"),
         TokenType.PLUS_EQ,
         AstTestFactory.identifier3("b"));
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     MethodElement staticElement = ElementFactory.methodElement("+", staticType);
     fromNode.staticElement = staticElement;
     fromNode.staticType = staticType;
@@ -192,7 +197,7 @@
         AstTestFactory.identifier3("a"),
         TokenType.PLUS,
         AstTestFactory.identifier3("b"));
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     MethodElement staticElement = ElementFactory.methodElement("+", staticType);
     fromNode.staticElement = staticElement;
     fromNode.staticType = staticType;
@@ -207,7 +212,7 @@
 
   void test_visitBooleanLiteral() {
     BooleanLiteral fromNode = AstTestFactory.booleanLiteral(true);
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     BooleanLiteral toNode = AstTestFactory.booleanLiteral(true);
     ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -217,7 +222,7 @@
   void test_visitCascadeExpression() {
     CascadeExpression fromNode = AstTestFactory.cascadeExpression(
         AstTestFactory.identifier3("a"), [AstTestFactory.identifier3("b")]);
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     CascadeExpression toNode = AstTestFactory.cascadeExpression(
         AstTestFactory.identifier3("a"), [AstTestFactory.identifier3("b")]);
@@ -239,7 +244,7 @@
         AstTestFactory.identifier3("c"),
         AstTestFactory.identifier3("a"),
         AstTestFactory.identifier3("b"));
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     ConditionalExpression toNode = AstTestFactory.conditionalExpression(
         AstTestFactory.identifier3("c"),
@@ -283,7 +288,7 @@
 
   void test_visitDoubleLiteral() {
     DoubleLiteral fromNode = AstTestFactory.doubleLiteral(1.0);
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     DoubleLiteral toNode = AstTestFactory.doubleLiteral(1.0);
     ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -305,7 +310,7 @@
             loopVariable: AstTestFactory.declaredIdentifier3('a'),
             iterable: AstTestFactory.identifier3('b'));
 
-    DartType typeB = ElementFactory.classElement2("B").type;
+    DartType typeB = interfaceType(ElementFactory.classElement2('B'));
 
     ForEachPartsWithDeclaration fromNode = createNode();
     (fromNode.iterable as SimpleIdentifier).staticType = typeB;
@@ -321,8 +326,8 @@
             identifier: AstTestFactory.identifier3('a'),
             iterable: AstTestFactory.identifier3('b'));
 
-    DartType typeA = ElementFactory.classElement2("A").type;
-    DartType typeB = ElementFactory.classElement2("B").type;
+    DartType typeA = interfaceType(ElementFactory.classElement2('A'));
+    DartType typeB = interfaceType(ElementFactory.classElement2('B'));
 
     ForEachPartsWithIdentifier fromNode = createNode();
     fromNode.identifier.staticType = typeA;
@@ -341,7 +346,7 @@
             iterable: AstTestFactory.identifier3('b')),
         body: AstTestFactory.identifier3('c'));
 
-    DartType typeC = ElementFactory.classElement2("C").type;
+    DartType typeC = interfaceType(ElementFactory.classElement2('C'));
 
     ForElement fromNode = createNode();
     (fromNode.body as SimpleIdentifier).staticType = typeC;
@@ -359,8 +364,8 @@
             condition: AstTestFactory.identifier3('b'),
             updaters: [AstTestFactory.identifier3('c')]);
 
-    DartType typeB = ElementFactory.classElement2("B").type;
-    DartType typeC = ElementFactory.classElement2("C").type;
+    DartType typeB = interfaceType(ElementFactory.classElement2('B'));
+    DartType typeC = interfaceType(ElementFactory.classElement2('C'));
 
     ForPartsWithDeclarations fromNode = createNode();
     (fromNode.condition as SimpleIdentifier).staticType = typeB;
@@ -378,9 +383,9 @@
         condition: AstTestFactory.identifier3('b'),
         updaters: [AstTestFactory.identifier3('c')]);
 
-    DartType typeA = ElementFactory.classElement2("A").type;
-    DartType typeB = ElementFactory.classElement2("B").type;
-    DartType typeC = ElementFactory.classElement2("C").type;
+    DartType typeA = interfaceType(ElementFactory.classElement2('A'));
+    DartType typeB = interfaceType(ElementFactory.classElement2('B'));
+    DartType typeC = interfaceType(ElementFactory.classElement2('C'));
 
     ForPartsWithExpression fromNode = createNode();
     (fromNode.initialization as SimpleIdentifier).staticType = typeA;
@@ -402,9 +407,9 @@
         body: AstTestFactory.expressionStatement(
             AstTestFactory.identifier3('c')));
 
-    DartType typeA = ElementFactory.classElement2("A").type;
-    DartType typeB = ElementFactory.classElement2("B").type;
-    DartType typeC = ElementFactory.classElement2("C").type;
+    DartType typeA = interfaceType(ElementFactory.classElement2('A'));
+    DartType typeB = interfaceType(ElementFactory.classElement2('B'));
+    DartType typeC = interfaceType(ElementFactory.classElement2('C'));
 
     ForStatement fromNode = createNode();
     ForEachPartsWithIdentifier fromForLoopParts = fromNode.forLoopParts;
@@ -430,9 +435,9 @@
         AstTestFactory.formalParameterList(),
         AstTestFactory.emptyFunctionBody());
     MethodElement element = ElementFactory.methodElement(
-        "m", ElementFactory.classElement2("C").type);
+        "m", interfaceType(ElementFactory.classElement2('C')));
     fromNode.declaredElement = element;
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     FunctionExpression toNode = AstTestFactory.functionExpression2(
         AstTestFactory.formalParameterList(),
@@ -447,7 +452,7 @@
         AstTestFactory.functionExpressionInvocation(
             AstTestFactory.identifier3("f"));
     MethodElement staticElement = ElementFactory.methodElement(
-        "m", ElementFactory.classElement2("C").type);
+        "m", interfaceType(ElementFactory.classElement2('C')));
     fromNode.staticElement = staticElement;
     FunctionExpressionInvocation toNode =
         AstTestFactory.functionExpressionInvocation(
@@ -469,9 +474,9 @@
         thenElement: AstTestFactory.identifier3('b'),
         elseElement: AstTestFactory.identifier3('c'));
 
-    DartType typeA = ElementFactory.classElement2("A").type;
-    DartType typeB = ElementFactory.classElement2("B").type;
-    DartType typeC = ElementFactory.classElement2("C").type;
+    DartType typeA = interfaceType(ElementFactory.classElement2('A'));
+    DartType typeB = interfaceType(ElementFactory.classElement2('B'));
+    DartType typeC = interfaceType(ElementFactory.classElement2('C'));
 
     IfElement fromNode = createNode();
     (fromNode.condition as SimpleIdentifier).staticType = typeA;
@@ -499,12 +504,12 @@
     IndexExpression fromNode = AstTestFactory.indexExpression(
         AstTestFactory.identifier3("a"), AstTestFactory.integer(0));
     MethodElement staticElement = ElementFactory.methodElement(
-        "m", ElementFactory.classElement2("C").type);
+        "m", interfaceType(ElementFactory.classElement2('C')));
     AuxiliaryElements auxiliaryElements =
         new AuxiliaryElements(staticElement, null);
     fromNode.auxiliaryElements = auxiliaryElements;
     fromNode.staticElement = staticElement;
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     IndexExpression toNode = AstTestFactory.indexExpression(
         AstTestFactory.identifier3("a"), AstTestFactory.integer(0));
@@ -521,7 +526,7 @@
     ConstructorElement staticElement = ElementFactory.constructorElement2(
         ElementFactory.classElement2("C"), null);
     fromNode.staticElement = staticElement;
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     InstanceCreationExpression toNode =
         AstTestFactory.instanceCreationExpression2(
@@ -533,7 +538,7 @@
 
   void test_visitIntegerLiteral() {
     IntegerLiteral fromNode = AstTestFactory.integer(2);
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     IntegerLiteral toNode = AstTestFactory.integer(2);
     ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -543,7 +548,7 @@
   void test_visitIsExpression() {
     IsExpression fromNode = AstTestFactory.isExpression(
         AstTestFactory.identifier3("x"), false, AstTestFactory.typeName4("A"));
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     IsExpression toNode = AstTestFactory.isExpression(
         AstTestFactory.identifier3("x"), false, AstTestFactory.typeName4("A"));
@@ -554,7 +559,7 @@
   void test_visitLibraryIdentifier() {
     LibraryIdentifier fromNode =
         AstTestFactory.libraryIdentifier([AstTestFactory.identifier3("lib")]);
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     LibraryIdentifier toNode =
         AstTestFactory.libraryIdentifier([AstTestFactory.identifier3("lib")]);
@@ -570,9 +575,9 @@
         [AstTestFactory.identifier3('b')],
         null);
 
-    DartType typeA = ElementFactory.classElement2("A").type;
-    DartType typeB = ElementFactory.classElement2("B").type;
-    DartType typeC = ElementFactory.classElement2("C").type;
+    DartType typeA = interfaceType(ElementFactory.classElement2('A'));
+    DartType typeB = interfaceType(ElementFactory.classElement2('B'));
+    DartType typeC = interfaceType(ElementFactory.classElement2('C'));
 
     ListLiteral fromNode = createNode();
     (fromNode.typeArguments.arguments[0] as TypeName).type = typeA;
@@ -588,7 +593,7 @@
 
   void test_visitMapLiteral() {
     SetOrMapLiteral fromNode = AstTestFactory.setOrMapLiteral(null, null);
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     SetOrMapLiteral toNode = AstTestFactory.setOrMapLiteral(null, null);
     ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -609,7 +614,7 @@
   void test_visitNamedExpression() {
     NamedExpression fromNode =
         AstTestFactory.namedExpression2("n", AstTestFactory.integer(0));
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     NamedExpression toNode =
         AstTestFactory.namedExpression2("n", AstTestFactory.integer(0));
@@ -619,7 +624,7 @@
 
   void test_visitNullLiteral() {
     NullLiteral fromNode = AstTestFactory.nullLiteral();
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     NullLiteral toNode = AstTestFactory.nullLiteral();
     ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -629,7 +634,7 @@
   void test_visitParenthesizedExpression() {
     ParenthesizedExpression fromNode =
         AstTestFactory.parenthesizedExpression(AstTestFactory.integer(0));
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     ParenthesizedExpression toNode =
         AstTestFactory.parenthesizedExpression(AstTestFactory.integer(0));
@@ -664,9 +669,9 @@
     PostfixExpression fromNode = AstTestFactory.postfixExpression(
         AstTestFactory.identifier3(variableName), TokenType.PLUS_PLUS);
     MethodElement staticElement = ElementFactory.methodElement(
-        "+", ElementFactory.classElement2("C").type);
+        "+", interfaceType(ElementFactory.classElement2('C')));
     fromNode.staticElement = staticElement;
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     PostfixExpression toNode = AstTestFactory.postfixExpression(
         AstTestFactory.identifier3(variableName), TokenType.PLUS_PLUS);
@@ -677,7 +682,7 @@
 
   void test_visitPrefixedIdentifier() {
     PrefixedIdentifier fromNode = AstTestFactory.identifier5("p", "f");
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     PrefixedIdentifier toNode = AstTestFactory.identifier5("p", "f");
     ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -687,9 +692,9 @@
   void test_visitPrefixExpression() {
     PrefixExpression fromNode = AstTestFactory.prefixExpression(
         TokenType.PLUS_PLUS, AstTestFactory.identifier3("x"));
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     MethodElement staticElement = ElementFactory.methodElement(
-        "+", ElementFactory.classElement2("C").type);
+        "+", interfaceType(ElementFactory.classElement2('C')));
     fromNode.staticElement = staticElement;
     fromNode.staticType = staticType;
     PrefixExpression toNode = AstTestFactory.prefixExpression(
@@ -702,7 +707,7 @@
   void test_visitPropertyAccess() {
     PropertyAccess fromNode =
         AstTestFactory.propertyAccess2(AstTestFactory.identifier3("x"), "y");
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     PropertyAccess toNode =
         AstTestFactory.propertyAccess2(AstTestFactory.identifier3("x"), "y");
@@ -724,7 +729,7 @@
 
   void test_visitRethrowExpression() {
     RethrowExpression fromNode = AstTestFactory.rethrowExpression();
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     RethrowExpression toNode = AstTestFactory.rethrowExpression();
     ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -737,10 +742,10 @@
             [AstTestFactory.typeName4('A'), AstTestFactory.typeName4('B')]),
         elements: [AstTestFactory.mapLiteralEntry3('c', 'd')]);
 
-    DartType typeA = ElementFactory.classElement2("A").type;
-    DartType typeB = ElementFactory.classElement2("B").type;
-    DartType typeC = ElementFactory.classElement2("C").type;
-    DartType typeD = ElementFactory.classElement2("D").type;
+    DartType typeA = interfaceType(ElementFactory.classElement2('A'));
+    DartType typeB = interfaceType(ElementFactory.classElement2('B'));
+    DartType typeC = interfaceType(ElementFactory.classElement2('C'));
+    DartType typeD = interfaceType(ElementFactory.classElement2('D'));
 
     SetOrMapLiteral fromNode = createNode();
     (fromNode.typeArguments.arguments[0] as TypeName).type = typeA;
@@ -764,8 +769,8 @@
             AstTestFactory.typeArgumentList([AstTestFactory.typeName4('A')]),
         elements: [AstTestFactory.identifier3('b')]);
 
-    DartType typeA = ElementFactory.classElement2("A").type;
-    DartType typeB = ElementFactory.classElement2("B").type;
+    DartType typeA = interfaceType(ElementFactory.classElement2('A'));
+    DartType typeB = interfaceType(ElementFactory.classElement2('B'));
 
     SetOrMapLiteral fromNode = createNode();
     (fromNode.typeArguments.arguments[0] as TypeName).type = typeA;
@@ -780,12 +785,12 @@
   void test_visitSimpleIdentifier() {
     SimpleIdentifier fromNode = AstTestFactory.identifier3("x");
     MethodElement staticElement = ElementFactory.methodElement(
-        "m", ElementFactory.classElement2("C").type);
+        "m", interfaceType(ElementFactory.classElement2('C')));
     AuxiliaryElements auxiliaryElements =
         new AuxiliaryElements(staticElement, null);
     fromNode.auxiliaryElements = auxiliaryElements;
     fromNode.staticElement = staticElement;
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     SimpleIdentifier toNode = AstTestFactory.identifier3("x");
     ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -796,7 +801,7 @@
 
   void test_visitSimpleStringLiteral() {
     SimpleStringLiteral fromNode = AstTestFactory.string2("abc");
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     SimpleStringLiteral toNode = AstTestFactory.string2("abc");
     ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -810,7 +815,7 @@
         expression: astFactory.listLiteral(
             null, null, null, [AstTestFactory.identifier3('a')], null));
 
-    DartType typeA = ElementFactory.classElement2("A").type;
+    DartType typeA = interfaceType(ElementFactory.classElement2('A'));
 
     SpreadElement fromNode = createNode();
     ((fromNode.expression as ListLiteral).elements[0] as SimpleIdentifier)
@@ -827,7 +832,7 @@
   void test_visitStringInterpolation() {
     StringInterpolation fromNode =
         AstTestFactory.string([AstTestFactory.interpolationString("a", "'a'")]);
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     StringInterpolation toNode =
         AstTestFactory.string([AstTestFactory.interpolationString("a", "'a'")]);
@@ -849,7 +854,7 @@
 
   void test_visitSuperExpression() {
     SuperExpression fromNode = AstTestFactory.superExpression();
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     SuperExpression toNode = AstTestFactory.superExpression();
     ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -858,7 +863,7 @@
 
   void test_visitSymbolLiteral() {
     SymbolLiteral fromNode = AstTestFactory.symbolLiteral(["s"]);
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     SymbolLiteral toNode = AstTestFactory.symbolLiteral(["s"]);
     ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -867,7 +872,7 @@
 
   void test_visitThisExpression() {
     ThisExpression fromNode = AstTestFactory.thisExpression();
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     ThisExpression toNode = AstTestFactory.thisExpression();
     ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -876,7 +881,7 @@
 
   void test_visitThrowExpression() {
     ThrowExpression fromNode = AstTestFactory.throwExpression();
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     ThrowExpression toNode = AstTestFactory.throwExpression();
     ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -885,7 +890,7 @@
 
   void test_visitTypeName() {
     TypeName fromNode = AstTestFactory.typeName4("C");
-    DartType type = ElementFactory.classElement2("C").type;
+    DartType type = interfaceType(ElementFactory.classElement2('C'));
     fromNode.type = type;
     TypeName toNode = AstTestFactory.typeName4("C");
     ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -894,10 +899,11 @@
 
   void _copyAndVerifyInvocation(
       InvocationExpression fromNode, InvocationExpression toNode) {
-    DartType staticType = ElementFactory.classElement2("C").type;
+    DartType staticType = interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
 
-    DartType staticInvokeType = ElementFactory.classElement2("C").type;
+    DartType staticInvokeType =
+        interfaceType(ElementFactory.classElement2('C'));
     fromNode.staticInvokeType = staticInvokeType;
 
     ResolutionCopier.copyResolutionData(fromNode, toNode);
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index 6644cb8..8d0b13e 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -839,8 +839,7 @@
 const c = [1, if (1 < 0) 2 else 3, 4];
 ''');
     DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type, typeProvider.listType.instantiate([typeProvider.intType]));
+    expect(result.type, typeProvider.listType2(typeProvider.intType));
     expect(result.toListValue().map((e) => e.toIntValue()), [1, 3, 4]);
   }
 
@@ -849,8 +848,7 @@
 const c = [1, if (1 < 0) 2, 3];
 ''');
     DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type, typeProvider.listType.instantiate([typeProvider.intType]));
+    expect(result.type, typeProvider.listType2(typeProvider.intType));
     expect(result.toListValue().map((e) => e.toIntValue()), [1, 3]);
   }
 
@@ -859,8 +857,7 @@
 const c = [1, if (1 > 0) 2 else 3, 4];
 ''');
     DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type, typeProvider.listType.instantiate([typeProvider.intType]));
+    expect(result.type, typeProvider.listType2(typeProvider.intType));
     expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 4]);
   }
 
@@ -869,8 +866,7 @@
 const c = [1, if (1 > 0) 2, 3];
 ''');
     DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type, typeProvider.listType.instantiate([typeProvider.intType]));
+    expect(result.type, typeProvider.listType2(typeProvider.intType));
     expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 3]);
   }
 
@@ -881,8 +877,7 @@
     DartObjectImpl result = _evaluateConstant('c');
     // The expected type ought to be `List<int>`, but type inference isn't yet
     // implemented.
-    expect(
-        result.type, typeProvider.listType.instantiate([typeProvider.intType]));
+    expect(result.type, typeProvider.listType2(typeProvider.intType));
     expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 3]);
   }
 
@@ -891,8 +886,7 @@
 const c = [1, ...[2, 3], 4];
 ''');
     DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type, typeProvider.listType.instantiate([typeProvider.intType]));
+    expect(result.type, typeProvider.listType2(typeProvider.intType));
     expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 3, 4]);
   }
 
@@ -901,10 +895,8 @@
 const c = {'a' : 1, if (1 < 0) 'b' : 2 else 'c' : 3, 'd' : 4};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type,
-        typeProvider.mapType
-            .instantiate([typeProvider.stringType, typeProvider.intType]));
+    expect(result.type,
+        typeProvider.mapType2(typeProvider.stringType, typeProvider.intType));
     Map<DartObject, DartObject> value = result.toMapValue();
     expect(value.keys.map((e) => e.toStringValue()),
         unorderedEquals(['a', 'c', 'd']));
@@ -916,10 +908,8 @@
 const c = {'a' : 1, if (1 < 0) 'b' : 2, 'c' : 3};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type,
-        typeProvider.mapType
-            .instantiate([typeProvider.stringType, typeProvider.intType]));
+    expect(result.type,
+        typeProvider.mapType2(typeProvider.stringType, typeProvider.intType));
     Map<DartObject, DartObject> value = result.toMapValue();
     expect(
         value.keys.map((e) => e.toStringValue()), unorderedEquals(['a', 'c']));
@@ -931,10 +921,8 @@
 const c = {'a' : 1, if (1 > 0) 'b' : 2 else 'c' : 3, 'd' : 4};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type,
-        typeProvider.mapType
-            .instantiate([typeProvider.stringType, typeProvider.intType]));
+    expect(result.type,
+        typeProvider.mapType2(typeProvider.stringType, typeProvider.intType));
     Map<DartObject, DartObject> value = result.toMapValue();
     expect(value.keys.map((e) => e.toStringValue()),
         unorderedEquals(['a', 'b', 'd']));
@@ -946,10 +934,8 @@
 const c = {'a' : 1, if (1 > 0) 'b' : 2, 'c' : 3};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type,
-        typeProvider.mapType
-            .instantiate([typeProvider.stringType, typeProvider.intType]));
+    expect(result.type,
+        typeProvider.mapType2(typeProvider.stringType, typeProvider.intType));
     Map<DartObject, DartObject> value = result.toMapValue();
     expect(value.keys.map((e) => e.toStringValue()),
         unorderedEquals(['a', 'b', 'c']));
@@ -963,10 +949,8 @@
 const c = {'a' : 1, if (1 > 0) if (2 > 1) {'b' : 2}, 'c' : 3};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type,
-        typeProvider.mapType
-            .instantiate([typeProvider.intType, typeProvider.intType]));
+    expect(result.type,
+        typeProvider.mapType2(typeProvider.intType, typeProvider.intType));
     Map<DartObject, DartObject> value = result.toMapValue();
     expect(value.keys.map((e) => e.toStringValue()),
         unorderedEquals(['a', 'b', 'c']));
@@ -978,10 +962,8 @@
 const c = {'a' : 1, ...{'b' : 2, 'c' : 3}, 'd' : 4};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type,
-        typeProvider.mapType
-            .instantiate([typeProvider.stringType, typeProvider.intType]));
+    expect(result.type,
+        typeProvider.mapType2(typeProvider.stringType, typeProvider.intType));
     Map<DartObject, DartObject> value = result.toMapValue();
     expect(value.keys.map((e) => e.toStringValue()),
         unorderedEquals(['a', 'b', 'c', 'd']));
@@ -994,8 +976,7 @@
 const c = {1, if (1 < 0) 2 else 3, 4};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type, typeProvider.setType.instantiate([typeProvider.intType]));
+    expect(result.type, typeProvider.setType2(typeProvider.intType));
     expect(result.toSetValue().map((e) => e.toIntValue()), [1, 3, 4]);
   }
 
@@ -1004,8 +985,7 @@
 const c = {1, if (1 < 0) 2, 3};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type, typeProvider.setType.instantiate([typeProvider.intType]));
+    expect(result.type, typeProvider.setType2(typeProvider.intType));
     expect(result.toSetValue().map((e) => e.toIntValue()), [1, 3]);
   }
 
@@ -1014,8 +994,7 @@
 const c = {1, if (1 > 0) 2 else 3, 4};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type, typeProvider.setType.instantiate([typeProvider.intType]));
+    expect(result.type, typeProvider.setType2(typeProvider.intType));
     expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 4]);
   }
 
@@ -1024,8 +1003,7 @@
 const c = {1, if (1 > 0) 2, 3};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type, typeProvider.setType.instantiate([typeProvider.intType]));
+    expect(result.type, typeProvider.setType2(typeProvider.intType));
     expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 3]);
   }
 
@@ -1034,8 +1012,7 @@
 const c = {1, if (1 > 0) if (2 > 1) 2, 3};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type, typeProvider.setType.instantiate([typeProvider.intType]));
+    expect(result.type, typeProvider.setType2(typeProvider.intType));
     expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 3]);
   }
 
@@ -1044,8 +1021,7 @@
 const c = {1, ...{2, 3}, 4};
 ''');
     DartObjectImpl result = _evaluateConstant('c');
-    expect(
-        result.type, typeProvider.setType.instantiate([typeProvider.intType]));
+    expect(result.type, typeProvider.setType2(typeProvider.intType));
     expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 3, 4]);
   }
 }
diff --git a/pkg/analyzer/test/src/dart/constant/value_test.dart b/pkg/analyzer/test/src/dart/constant/value_test.dart
index 521182b..f337c05 100644
--- a/pkg/analyzer/test/src/dart/constant/value_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/value_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/testing/test_type_provider.dart';
@@ -289,19 +290,35 @@
   }
 
   void test_equalEqual_list_empty() {
-    _assertEqualEqual(null, _listValue(), _listValue());
+    _assertEqualEqual(
+      null,
+      _listValue(_typeProvider.intType, []),
+      _listValue(_typeProvider.intType, []),
+    );
   }
 
   void test_equalEqual_list_false() {
-    _assertEqualEqual(null, _listValue(), _listValue());
+    _assertEqualEqual(
+      null,
+      _listValue(_typeProvider.intType, []),
+      _listValue(_typeProvider.intType, []),
+    );
   }
 
   void test_equalEqual_map_empty() {
-    _assertEqualEqual(null, _mapValue(), _mapValue());
+    _assertEqualEqual(
+      null,
+      _mapValue(_typeProvider.intType, _typeProvider.stringType, []),
+      _mapValue(_typeProvider.intType, _typeProvider.stringType, []),
+    );
   }
 
   void test_equalEqual_map_false() {
-    _assertEqualEqual(null, _mapValue(), _mapValue());
+    _assertEqualEqual(
+      null,
+      _mapValue(_typeProvider.intType, _typeProvider.stringType, []),
+      _mapValue(_typeProvider.intType, _typeProvider.stringType, []),
+    );
   }
 
   void test_equalEqual_null() {
@@ -325,26 +342,38 @@
 
   void test_equals_list_false_differentSizes() {
     expect(
-        _listValue([_boolValue(true)]) ==
-            _listValue([_boolValue(true), _boolValue(false)]),
+        _listValue(_typeProvider.boolType, [_boolValue(true)]) ==
+            _listValue(
+                _typeProvider.boolType, [_boolValue(true), _boolValue(false)]),
         isFalse);
   }
 
   void test_equals_list_false_sameSize() {
-    expect(_listValue([_boolValue(true)]) == _listValue([_boolValue(false)]),
+    expect(
+        _listValue(_typeProvider.boolType, [_boolValue(true)]) ==
+            _listValue(_typeProvider.boolType, [_boolValue(false)]),
         isFalse);
   }
 
   void test_equals_list_true_empty() {
-    expect(_listValue(), _listValue());
+    expect(
+      _listValue(_typeProvider.intType, []),
+      _listValue(_typeProvider.intType, []),
+    );
   }
 
   void test_equals_list_true_nonEmpty() {
-    expect(_listValue([_boolValue(true)]), _listValue([_boolValue(true)]));
+    expect(
+      _listValue(_typeProvider.boolType, [_boolValue(true)]),
+      _listValue(_typeProvider.boolType, [_boolValue(true)]),
+    );
   }
 
   void test_equals_map_true_empty() {
-    expect(_mapValue(), _mapValue());
+    expect(
+      _mapValue(_typeProvider.intType, _typeProvider.stringType, []),
+      _mapValue(_typeProvider.intType, _typeProvider.stringType, []),
+    );
   }
 
   void test_equals_symbol_false() {
@@ -386,27 +415,29 @@
   }
 
   void test_getValue_list_empty() {
-    Object result = _listValue().toListValue();
+    Object result = _listValue(_typeProvider.intType, []).toListValue();
     _assertInstanceOfObjectArray(result);
     List<Object> array = result as List<Object>;
     expect(array, hasLength(0));
   }
 
   void test_getValue_list_valid() {
-    Object result = _listValue([_intValue(23)]).toListValue();
+    Object result =
+        _listValue(_typeProvider.intType, [_intValue(23)]).toListValue();
     _assertInstanceOfObjectArray(result);
     List<Object> array = result as List<Object>;
     expect(array, hasLength(1));
   }
 
   void test_getValue_map_empty() {
-    Map result = _mapValue().toMapValue();
+    Map result = _mapValue(_typeProvider.intType, _typeProvider.stringType, [])
+        .toMapValue();
     expect(result, hasLength(0));
   }
 
   void test_getValue_map_valid() {
-    Map result =
-        _mapValue([_stringValue("key"), _stringValue("value")]).toMapValue();
+    Map result = _mapValue(_typeProvider.stringType, _typeProvider.stringType,
+        [_stringValue("key"), _stringValue("value")]).toMapValue();
     expect(result, hasLength(1));
   }
 
@@ -415,16 +446,14 @@
   }
 
   void test_getValue_set_empty() {
-    Object result = _setValue().toSetValue();
-    _assertInstanceOfObjectArray(result);
-    Set<Object> set = result as Set<Object>;
+    DartObjectImpl object = _setValue(_typeProvider.intType, null);
+    Set<DartObject> set = object.toSetValue();
     expect(set, hasLength(0));
   }
 
   void test_getValue_set_valid() {
-    Object result = _setValue(new Set.from([_intValue(23)])).toSetValue();
-    _assertInstanceOfObjectArray(result);
-    Set<Object> set = result as Set<Object>;
+    DartObjectImpl object = _setValue(_typeProvider.intType, {_intValue(23)});
+    Set<DartObject> set = object.toSetValue();
     expect(set, hasLength(1));
   }
 
@@ -604,20 +633,25 @@
   }
 
   void test_hasKnownValue_list_empty() {
-    expect(_listValue().hasKnownValue, isTrue);
+    expect(_listValue(_typeProvider.intType, []).hasKnownValue, isTrue);
   }
 
   void test_hasKnownValue_list_valid() {
-    expect(_listValue([_intValue(23)]).hasKnownValue, isTrue);
+    expect(_listValue(_typeProvider.intType, [_intValue(23)]).hasKnownValue,
+        isTrue);
   }
 
   void test_hasKnownValue_map_empty() {
-    expect(_mapValue().hasKnownValue, isTrue);
+    expect(
+        _mapValue(_typeProvider.intType, _typeProvider.stringType, [])
+            .hasKnownValue,
+        isTrue);
   }
 
   void test_hasKnownValue_map_valid() {
     expect(
-        _mapValue([_stringValue("key"), _stringValue("value")]).hasKnownValue,
+        _mapValue(_typeProvider.stringType, _typeProvider.stringType,
+            [_stringValue("key"), _stringValue("value")]).hasKnownValue,
         isTrue);
   }
 
@@ -670,21 +704,36 @@
   }
 
   void test_identical_list_empty() {
-    _assertIdentical(_boolValue(true), _listValue(), _listValue());
+    _assertIdentical(
+      _boolValue(true),
+      _listValue(_typeProvider.intType, []),
+      _listValue(_typeProvider.intType, []),
+    );
   }
 
   void test_identical_list_false() {
-    _assertIdentical(
-        _boolValue(false), _listValue(), _listValue([_intValue(3)]));
+    _assertIdentical(_boolValue(false), _listValue(_typeProvider.intType, []),
+        _listValue(_typeProvider.intType, [_intValue(3)]));
   }
 
   void test_identical_map_empty() {
-    _assertIdentical(_boolValue(true), _mapValue(), _mapValue());
+    _assertIdentical(
+      _boolValue(true),
+      _mapValue(_typeProvider.intType, _typeProvider.stringType, []),
+      _mapValue(_typeProvider.intType, _typeProvider.stringType, []),
+    );
   }
 
   void test_identical_map_false() {
-    _assertIdentical(_boolValue(false), _mapValue(),
-        _mapValue([_intValue(1), _intValue(2)]));
+    _assertIdentical(
+      _boolValue(false),
+      _mapValue(_typeProvider.intType, _typeProvider.intType, []),
+      _mapValue(
+        _typeProvider.intType,
+        _typeProvider.intType,
+        [_intValue(1), _intValue(2)],
+      ),
+    );
   }
 
   void test_identical_null() {
@@ -788,7 +837,8 @@
   }
 
   void test_isBoolNumStringOrNull_list() {
-    expect(_listValue().isBoolNumStringOrNull, isFalse);
+    expect(
+        _listValue(_typeProvider.intType, []).isBoolNumStringOrNull, isFalse);
   }
 
   void test_isBoolNumStringOrNull_null() {
@@ -1923,28 +1973,35 @@
   }
 
   DartObjectImpl _listValue(
-      [List<DartObjectImpl> elements = const <DartObjectImpl>[]]) {
-    return new DartObjectImpl(_typeProvider.listType, new ListState(elements));
+    DartType elementType,
+    List<DartObjectImpl> elements,
+  ) {
+    return DartObjectImpl(
+      _typeProvider.listType2(elementType),
+      ListState(elements),
+    );
   }
 
-  DartObjectImpl _mapValue(
-      [List<DartObjectImpl> keyElementPairs = const <DartObjectImpl>[]]) {
+  DartObjectImpl _mapValue(DartType keyType, DartType valueType,
+      List<DartObjectImpl> keyElementPairs) {
     Map<DartObjectImpl, DartObjectImpl> map =
         new Map<DartObjectImpl, DartObjectImpl>();
     int count = keyElementPairs.length;
     for (int i = 0; i < count;) {
       map[keyElementPairs[i++]] = keyElementPairs[i++];
     }
-    return new DartObjectImpl(_typeProvider.mapType, new MapState(map));
+    return DartObjectImpl(
+      _typeProvider.mapType2(keyType, valueType),
+      MapState(map),
+    );
   }
 
   DartObjectImpl _nullValue() {
     return new DartObjectImpl(_typeProvider.nullType, NullState.NULL_STATE);
   }
 
-  DartObjectImpl _setValue([Set<DartObjectImpl> elements]) {
-    return new DartObjectImpl(_typeProvider.setType,
-        new SetState(elements ?? new Set<DartObjectImpl>()));
+  DartObjectImpl _setValue(DartType type, Set<DartObjectImpl> elements) {
+    return DartObjectImpl(type, SetState(elements ?? Set<DartObjectImpl>()));
   }
 
   DartObjectImpl _stringValue(String value) {
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index 15d7978..a3d5a04 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -5,17 +5,21 @@
 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/dart/element/handle.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
+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';
 import 'package:analyzer/src/generated/testing/test_type_provider.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';
 import '../../../generated/test_support.dart';
 import '../resolution/driver_resolution.dart';
 
@@ -37,16 +41,29 @@
   });
 }
 
+class AbstractTypeTest with ElementsTypesMixin {
+  AnalysisContext _analysisContext;
+  TypeProvider _typeProvider;
+
+  TypeProvider get typeProvider => _typeProvider;
+
+  void setUp() {
+    _analysisContext = TestAnalysisContext();
+    _typeProvider = _analysisContext.typeProvider;
+  }
+}
+
 @reflectiveTest
-class ClassElementImplTest {
+class ClassElementImplTest extends AbstractTypeTest {
   void test_getAllSupertypes_interface() {
-    ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classB = ElementFactory.classElement("B", classA.type);
+    ClassElement classA = class_(name: 'A');
+    ClassElement classB =
+        ElementFactory.classElement("B", interfaceType(classA));
     ClassElementImpl elementC = ElementFactory.classElement2("C");
     InterfaceType typeObject = classA.supertype;
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = elementC.type;
+    InterfaceType typeA = interfaceType(classA);
+    InterfaceType typeB = interfaceType(classB);
+    InterfaceType typeC = interfaceType(elementC);
     elementC.interfaces = <InterfaceType>[typeB];
     List<InterfaceType> supers = elementC.allSupertypes;
     List<InterfaceType> types = new List<InterfaceType>();
@@ -58,13 +75,14 @@
   }
 
   void test_getAllSupertypes_mixins() {
-    ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement2("C");
+    ClassElement classA = class_(name: 'A');
+    ClassElement classB =
+        ElementFactory.classElement("B", interfaceType(classA));
+    var classC = ElementFactory.classElement2("C");
     InterfaceType typeObject = classA.supertype;
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
+    InterfaceType typeA = interfaceType(classA);
+    InterfaceType typeB = interfaceType(classB);
+    InterfaceType typeC = interfaceType(classC);
     classC.mixins = <InterfaceType>[typeB];
     List<InterfaceType> supers = classC.allSupertypes;
     List<InterfaceType> types = new List<InterfaceType>();
@@ -76,15 +94,16 @@
   }
 
   void test_getAllSupertypes_recursive() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    classA.supertype = classB.type;
+    var classA = class_(name: 'A');
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
+    classA.supertype = interfaceType(classB);
     List<InterfaceType> supers = classB.allSupertypes;
     expect(supers, hasLength(1));
   }
 
   void test_getField() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String fieldName = "f";
     FieldElementImpl field =
         ElementFactory.fieldElement(fieldName, false, false, false, null);
@@ -96,7 +115,7 @@
   }
 
   void test_getMethod_declared() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElement method = ElementFactory.methodElement(methodName, null);
     classA.methods = <MethodElement>[method];
@@ -104,7 +123,7 @@
   }
 
   void test_getMethod_undeclared() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElement method = ElementFactory.methodElement(methodName, null);
     classA.methods = <MethodElement>[method];
@@ -112,60 +131,66 @@
   }
 
   void test_hasNonFinalField_false_const() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     classA.fields = <FieldElement>[
-      ElementFactory.fieldElement("f", false, false, true, classA.type)
+      ElementFactory.fieldElement(
+          "f", false, false, true, interfaceType(classA))
     ];
     expect(classA.hasNonFinalField, isFalse);
   }
 
   void test_hasNonFinalField_false_final() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     classA.fields = <FieldElement>[
-      ElementFactory.fieldElement("f", false, true, false, classA.type)
+      ElementFactory.fieldElement(
+          "f", false, true, false, interfaceType(classA))
     ];
     expect(classA.hasNonFinalField, isFalse);
   }
 
   void test_hasNonFinalField_false_recursive() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    classA.supertype = classB.type;
+    var classA = class_(name: 'A');
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
+    classA.supertype = interfaceType(classB);
     expect(classA.hasNonFinalField, isFalse);
   }
 
   void test_hasNonFinalField_true_immediate() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     classA.fields = <FieldElement>[
-      ElementFactory.fieldElement("f", false, false, false, classA.type)
+      ElementFactory.fieldElement(
+          "f", false, false, false, interfaceType(classA))
     ];
     expect(classA.hasNonFinalField, isTrue);
   }
 
   void test_hasNonFinalField_true_inherited() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    var classA = class_(name: 'A');
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
     classA.fields = <FieldElement>[
-      ElementFactory.fieldElement("f", false, false, false, classA.type)
+      ElementFactory.fieldElement(
+          "f", false, false, false, interfaceType(classA))
     ];
     expect(classB.hasNonFinalField, isTrue);
   }
 
   void test_hasStaticMember_false_empty() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     // no members
     expect(classA.hasStaticMember, isFalse);
   }
 
   void test_hasStaticMember_false_instanceMethod() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     MethodElement method = ElementFactory.methodElement("foo", null);
     classA.methods = <MethodElement>[method];
     expect(classA.hasStaticMember, isFalse);
   }
 
   void test_hasStaticMember_instanceGetter() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     PropertyAccessorElement getter =
         ElementFactory.getterElement("foo", false, null);
     classA.accessors = <PropertyAccessorElement>[getter];
@@ -173,7 +198,7 @@
   }
 
   void test_hasStaticMember_true_getter() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     PropertyAccessorElementImpl getter =
         ElementFactory.getterElement("foo", false, null);
     classA.accessors = <PropertyAccessorElement>[getter];
@@ -183,7 +208,7 @@
   }
 
   void test_hasStaticMember_true_method() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     MethodElementImpl method = ElementFactory.methodElement("foo", null);
     classA.methods = <MethodElement>[method];
     // "foo" is static
@@ -192,7 +217,7 @@
   }
 
   void test_hasStaticMember_true_setter() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     PropertyAccessorElementImpl setter =
         ElementFactory.setterElement("foo", false, null);
     classA.accessors = <PropertyAccessorElement>[setter];
@@ -220,7 +245,7 @@
     //   m() {}
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElement method = ElementFactory.methodElement(methodName, null);
     classA.methods = <MethodElement>[method];
@@ -234,7 +259,7 @@
     //   m();
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElementImpl method = ElementFactory.methodElement(methodName, null);
     method.isAbstract = true;
@@ -252,12 +277,13 @@
     //   m();
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElement inheritedMethod =
         ElementFactory.methodElement(methodName, null);
     classA.methods = <MethodElement>[inheritedMethod];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
     MethodElementImpl method = ElementFactory.methodElement(methodName, null);
     method.isAbstract = true;
     classB.methods = <MethodElement>[method];
@@ -275,12 +301,13 @@
     //   m() {}
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElement inheritedMethod =
         ElementFactory.methodElement(methodName, null);
     classA.methods = <MethodElement>[inheritedMethod];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
     MethodElement method = ElementFactory.methodElement(methodName, null);
     classB.methods = <MethodElement>[method];
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
@@ -296,14 +323,15 @@
     //   m() {}
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     classA.isAbstract = true;
     String methodName = "m";
     MethodElementImpl inheritedMethod =
         ElementFactory.methodElement(methodName, null);
     inheritedMethod.isAbstract = true;
     classA.methods = <MethodElement>[inheritedMethod];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
     MethodElement method = ElementFactory.methodElement(methodName, null);
     classB.methods = <MethodElement>[method];
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
@@ -318,12 +346,13 @@
     // class B extends A {
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElement inheritedMethod =
         ElementFactory.methodElement(methodName, null);
     classA.methods = <MethodElement>[inheritedMethod];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA, classB];
     expect(classB.lookUpConcreteMethod(methodName, library),
@@ -334,7 +363,7 @@
     // class A {
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA];
     expect(classA.lookUpConcreteMethod("m", library), isNull);
@@ -345,7 +374,7 @@
     //   get g {}
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String getterName = "g";
     PropertyAccessorElement getter =
         ElementFactory.getterElement(getterName, false, null);
@@ -362,12 +391,13 @@
     // class B extends A {
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String getterName = "g";
     PropertyAccessorElement getter =
         ElementFactory.getterElement(getterName, false, null);
     classA.accessors = <PropertyAccessorElement>[getter];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA, classB];
     expect(classB.lookUpGetter(getterName, library), same(getter));
@@ -377,7 +407,7 @@
     // class A {
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA];
     expect(classA.lookUpGetter("g", library), isNull);
@@ -389,9 +419,10 @@
     // class B extends A {
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    classA.supertype = classB.type;
+    var classA = class_(name: 'A');
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
+    classA.supertype = interfaceType(classB);
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA, classB];
     expect(classA.lookUpGetter("g", library), isNull);
@@ -402,7 +433,7 @@
     //   get g {}
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String getterName = "g";
     PropertyAccessorElement getter =
         ElementFactory.getterElement(getterName, false, null);
@@ -419,12 +450,13 @@
     // class B extends A {
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String getterName = "g";
     PropertyAccessorElement inheritedGetter =
         ElementFactory.getterElement(getterName, false, null);
     classA.accessors = <PropertyAccessorElement>[inheritedGetter];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA, classB];
     expect(classB.lookUpInheritedConcreteGetter(getterName, library),
@@ -435,7 +467,7 @@
     // class A {
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA];
     expect(classA.lookUpInheritedConcreteGetter("g", library), isNull);
@@ -447,9 +479,10 @@
     // class B extends A {
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    classA.supertype = classB.type;
+    var classA = class_(name: 'A');
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
+    classA.supertype = interfaceType(classB);
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA, classB];
     expect(classA.lookUpInheritedConcreteGetter("g", library), isNull);
@@ -460,7 +493,7 @@
     //   m() {}
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElement method = ElementFactory.methodElement(methodName, null);
     classA.methods = <MethodElement>[method];
@@ -477,12 +510,13 @@
     //   m();
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElement inheritedMethod =
         ElementFactory.methodElement(methodName, null);
     classA.methods = <MethodElement>[inheritedMethod];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
     MethodElementImpl method = ElementFactory.methodElement(methodName, null);
     method.isAbstract = true;
     classB.methods = <MethodElement>[method];
@@ -500,12 +534,13 @@
     //   m() {}
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElement inheritedMethod =
         ElementFactory.methodElement(methodName, null);
     classA.methods = <MethodElement>[inheritedMethod];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
     MethodElement method = ElementFactory.methodElement(methodName, null);
     classB.methods = <MethodElement>[method];
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
@@ -522,14 +557,15 @@
     //   m() {}
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     classA.isAbstract = true;
     String methodName = "m";
     MethodElementImpl inheritedMethod =
         ElementFactory.methodElement(methodName, null);
     inheritedMethod.isAbstract = true;
     classA.methods = <MethodElement>[inheritedMethod];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
     MethodElement method = ElementFactory.methodElement(methodName, null);
     classB.methods = <MethodElement>[method];
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
@@ -549,17 +585,19 @@
     //   m() {}
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElement inheritedMethod =
         ElementFactory.methodElement(methodName, null);
     classA.methods = <MethodElement>[inheritedMethod];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
     MethodElementImpl abstractMethod =
         ElementFactory.methodElement(methodName, null);
     abstractMethod.isAbstract = true;
     classB.methods = <MethodElement>[abstractMethod];
-    ClassElementImpl classC = ElementFactory.classElement("C", classB.type);
+    ClassElementImpl classC =
+        ElementFactory.classElement("C", interfaceType(classB));
     MethodElementImpl method = ElementFactory.methodElement(methodName, null);
     classC.methods = <MethodElement>[method];
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
@@ -575,12 +613,13 @@
     // class B extends A {
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElement inheritedMethod =
         ElementFactory.methodElement(methodName, null);
     classA.methods = <MethodElement>[inheritedMethod];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA, classB];
     expect(classB.lookUpInheritedConcreteMethod(methodName, library),
@@ -591,7 +630,7 @@
     // class A {
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA];
     expect(classA.lookUpInheritedConcreteMethod("m", library), isNull);
@@ -602,7 +641,7 @@
     //   set g(x) {}
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String setterName = "s";
     PropertyAccessorElement setter =
         ElementFactory.setterElement(setterName, false, null);
@@ -619,12 +658,13 @@
     // class B extends A {
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String setterName = "s";
     PropertyAccessorElement setter =
         ElementFactory.setterElement(setterName, false, null);
     classA.accessors = <PropertyAccessorElement>[setter];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA, classB];
     expect(classB.lookUpInheritedConcreteSetter(setterName, library),
@@ -635,7 +675,7 @@
     // class A {
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA];
     expect(classA.lookUpInheritedConcreteSetter("s", library), isNull);
@@ -647,9 +687,10 @@
     // class B extends A {
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    classA.supertype = classB.type;
+    var classA = class_(name: 'A');
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
+    classA.supertype = interfaceType(classB);
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA, classB];
     expect(classA.lookUpInheritedConcreteSetter("s", library), isNull);
@@ -660,7 +701,7 @@
     //   m() {}
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElement method = ElementFactory.methodElement(methodName, null);
     classA.methods = <MethodElement>[method];
@@ -677,12 +718,13 @@
     //   m() {}
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElement inheritedMethod =
         ElementFactory.methodElement(methodName, null);
     classA.methods = <MethodElement>[inheritedMethod];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
     MethodElement method = ElementFactory.methodElement(methodName, null);
     classB.methods = <MethodElement>[method];
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
@@ -698,12 +740,13 @@
     // class B extends A {
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElement inheritedMethod =
         ElementFactory.methodElement(methodName, null);
     classA.methods = <MethodElement>[inheritedMethod];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA, classB];
     expect(classB.lookUpInheritedMethod(methodName, library),
@@ -714,7 +757,7 @@
     // class A {
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA];
     expect(classA.lookUpInheritedMethod("m", library), isNull);
@@ -722,7 +765,7 @@
 
   void test_lookUpMethod_declared() {
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElement method = ElementFactory.methodElement(methodName, null);
     classA.methods = <MethodElement>[method];
@@ -733,11 +776,12 @@
 
   void test_lookUpMethod_inherited() {
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElement method = ElementFactory.methodElement(methodName, null);
     classA.methods = <MethodElement>[method];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA, classB];
     expect(classB.lookUpMethod(methodName, library), same(method));
@@ -745,7 +789,7 @@
 
   void test_lookUpMethod_undeclared() {
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA];
     expect(classA.lookUpMethod("m", library), isNull);
@@ -753,9 +797,10 @@
 
   void test_lookUpMethod_undeclared_recursive() {
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    classA.supertype = classB.type;
+    var classA = class_(name: 'A');
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
+    classA.supertype = interfaceType(classB);
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA, classB];
     expect(classA.lookUpMethod("m", library), isNull);
@@ -766,7 +811,7 @@
     //   set g(x) {}
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String setterName = "s";
     PropertyAccessorElement setter =
         ElementFactory.setterElement(setterName, false, null);
@@ -783,12 +828,13 @@
     // class B extends A {
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String setterName = "s";
     PropertyAccessorElement setter =
         ElementFactory.setterElement(setterName, false, null);
     classA.accessors = <PropertyAccessorElement>[setter];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA, classB];
     expect(classB.lookUpSetter(setterName, library), same(setter));
@@ -798,7 +844,7 @@
     // class A {
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA];
     expect(classA.lookUpSetter("s", library), isNull);
@@ -810,9 +856,10 @@
     // class B extends A {
     // }
     LibraryElementImpl library = _newLibrary();
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    classA.supertype = classB.type;
+    var classA = class_(name: 'A');
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
+    classA.supertype = interfaceType(classB);
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA, classB];
     expect(classA.lookUpSetter("s", library), isNull);
@@ -896,15 +943,23 @@
 }
 
 @reflectiveTest
-class ElementImplTest extends EngineTestCase {
+class ElementImplTest extends AbstractTypeTest {
   void test_equals() {
     LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+        ElementFactory.library(_analysisContext, "lib");
     ClassElementImpl classElement = ElementFactory.classElement2("C");
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classElement];
     FieldElement field = ElementFactory.fieldElement(
-        "next", false, false, false, classElement.type);
+      "next",
+      false,
+      false,
+      false,
+      classElement.instantiate(
+        typeArguments: [],
+        nullabilitySuffix: NullabilitySuffix.star,
+      ),
+    );
     classElement.fields = <FieldElement>[field];
     expect(field == field, isTrue);
     expect(field == field.getter, isFalse);
@@ -913,18 +968,19 @@
   }
 
   void test_isAccessibleIn_private_differentLibrary() {
-    AnalysisContext context = createAnalysisContext();
-    LibraryElementImpl library1 = ElementFactory.library(context, "lib1");
+    LibraryElementImpl library1 =
+        ElementFactory.library(_analysisContext, "lib1");
     ClassElement classElement = ElementFactory.classElement2("_C");
     (library1.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classElement];
-    LibraryElementImpl library2 = ElementFactory.library(context, "lib2");
+    LibraryElementImpl library2 =
+        ElementFactory.library(_analysisContext, "lib2");
     expect(classElement.isAccessibleIn(library2), isFalse);
   }
 
   void test_isAccessibleIn_private_sameLibrary() {
     LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+        ElementFactory.library(_analysisContext, "lib");
     ClassElement classElement = ElementFactory.classElement2("_C");
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classElement];
@@ -932,18 +988,19 @@
   }
 
   void test_isAccessibleIn_public_differentLibrary() {
-    AnalysisContext context = createAnalysisContext();
-    LibraryElementImpl library1 = ElementFactory.library(context, "lib1");
+    LibraryElementImpl library1 =
+        ElementFactory.library(_analysisContext, "lib1");
     ClassElement classElement = ElementFactory.classElement2("C");
     (library1.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classElement];
-    LibraryElementImpl library2 = ElementFactory.library(context, "lib2");
+    LibraryElementImpl library2 =
+        ElementFactory.library(_analysisContext, "lib2");
     expect(classElement.isAccessibleIn(library2), isTrue);
   }
 
   void test_isAccessibleIn_public_sameLibrary() {
     LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+        ElementFactory.library(_analysisContext, "lib");
     ClassElement classElement = ElementFactory.classElement2("C");
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classElement];
@@ -981,7 +1038,7 @@
   }
 
   void test_SORT_BY_OFFSET() {
-    ClassElementImpl classElementA = ElementFactory.classElement2("A");
+    ClassElementImpl classElementA = class_(name: 'A');
     classElementA.nameOffset = 1;
     ClassElementImpl classElementB = ElementFactory.classElement2("B");
     classElementB.nameOffset = 2;
@@ -1075,7 +1132,7 @@
 }
 
 @reflectiveTest
-class FunctionTypeImplTest extends EngineTestCase {
+class FunctionTypeImplTest extends AbstractTypeTest {
   void test_creation() {
     expect(
         new FunctionTypeImpl(
@@ -1088,13 +1145,16 @@
     var t = ElementFactory.genericTypeAliasElement('t');
     var u = ElementFactory.genericTypeAliasElement('u');
     var v = ElementFactory.genericTypeAliasElement('v');
-    s.function.returnType = t.type;
-    t.function.returnType = s.type;
-    u.function.returnType = v.type;
-    v.function.returnType = u.type;
+    s.function.returnType = functionTypeAliasType(t);
+    t.function.returnType = functionTypeAliasType(s);
+    u.function.returnType = functionTypeAliasType(v);
+    v.function.returnType = functionTypeAliasType(u);
     // We don't care whether the types compare equal or not.  We just need the
     // computation to terminate.
-    expect(s.type == u.type, new TypeMatcher<bool>());
+    expect(
+      functionTypeAliasType(s) == functionTypeAliasType(u),
+      new TypeMatcher<bool>(),
+    );
   }
 
   void test_getElement() {
@@ -1239,16 +1299,16 @@
   void test_hashCode_recursive() {
     var s = ElementFactory.genericTypeAliasElement('s');
     var t = ElementFactory.genericTypeAliasElement('t');
-    s.function.returnType = t.type;
-    t.function.returnType = s.type;
+    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(t.type.hashCode, new TypeMatcher<int>());
+    expect(functionTypeAliasType(t).hashCode, new TypeMatcher<int>());
   }
 
   void test_isAssignableTo_normalAndPositionalArgs() {
     // ([a]) -> void <: (a) -> void
-    ClassElement a = ElementFactory.classElement2("A");
+    ClassElement a = class_(name: 'A');
     FunctionType t =
         ElementFactory.functionElement6("t", null, <ClassElement>[a]).type;
     FunctionType s =
@@ -1276,7 +1336,7 @@
     // class C
     // ! () -> void <: C
     FunctionType f = ElementFactory.functionElement("f").type;
-    InterfaceType t = ElementFactory.classElement2("C").type;
+    InterfaceType t = interfaceType(class_(name: 'C'));
     expect(f.isSubtypeOf(t), isFalse);
   }
 
@@ -1296,8 +1356,8 @@
     // B extends A
     // ({name: A}) -> void <: ({name: B}) -> void
     // ({name: B}) -> void <: ({name: A}) -> void
-    ClassElement a = ElementFactory.classElement2("A");
-    ClassElement b = ElementFactory.classElement("B", a.type);
+    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(
@@ -1308,12 +1368,8 @@
 
   void test_isSubtypeOf_namedParameters_isNotAssignable() {
     // ! ({name: A}) -> void <: ({name: B}) -> void
-    FunctionType t = ElementFactory.functionElement4(
-        "t",
-        null,
-        null,
-        <String>["name"],
-        <ClassElement>[ElementFactory.classElement2("A")]).type;
+    FunctionType t = ElementFactory.functionElement4("t", null, null,
+        <String>["name"], <ClassElement>[class_(name: 'A')]).type;
     FunctionType s = ElementFactory.functionElement4(
         "s",
         null,
@@ -1329,8 +1385,8 @@
     // void s({A diff}) {}
     // ! t <: s
     // ! s <: t
-    ClassElement a = ElementFactory.classElement2("A");
-    ClassElement b = ElementFactory.classElement("B", a.type);
+    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(
@@ -1342,8 +1398,8 @@
   void test_isSubtypeOf_namedParameters_orderOfParams() {
     // B extends A
     // ({A: A, B: B}) -> void <: ({B: B, A: A}) -> void
-    ClassElement a = ElementFactory.classElement2("A");
-    ClassElement b = ElementFactory.classElement("B", a.type);
+    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(
@@ -1354,8 +1410,8 @@
   void test_isSubtypeOf_namedParameters_orderOfParams2() {
     // B extends A
     // ! ({B: B}) -> void <: ({B: B, A: A}) -> void
-    ClassElement a = ElementFactory.classElement2("A");
-    ClassElement b = ElementFactory.classElement("B", a.type);
+    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(
@@ -1366,8 +1422,8 @@
   void test_isSubtypeOf_namedParameters_orderOfParams3() {
     // B extends A
     // ({A: A, B: B}) -> void <: ({A: A}) -> void
-    ClassElement a = ElementFactory.classElement2("A");
-    ClassElement b = ElementFactory.classElement("B", a.type);
+    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(
@@ -1378,8 +1434,8 @@
   void test_isSubtypeOf_namedParameters_sHasMoreParams() {
     // B extends A
     // ! ({name: A}) -> void <: ({name: B, name2: B}) -> void
-    ClassElement a = ElementFactory.classElement2("A");
-    ClassElement b = ElementFactory.classElement("B", a.type);
+    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(
@@ -1390,8 +1446,8 @@
   void test_isSubtypeOf_namedParameters_tHasMoreParams() {
     // B extends A
     // ({name: A, name2: A}) -> void <: ({name: B}) -> void
-    ClassElement a = ElementFactory.classElement2("A");
-    ClassElement b = ElementFactory.classElement("B", a.type);
+    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(
@@ -1401,7 +1457,7 @@
 
   void test_isSubtypeOf_normalAndPositionalArgs_1() {
     // ([a]) -> void <: (a) -> void
-    ClassElement a = ElementFactory.classElement2("A");
+    ClassElement a = class_(name: 'A');
     FunctionType t =
         ElementFactory.functionElement6("t", null, <ClassElement>[a]).type;
     FunctionType s =
@@ -1412,7 +1468,7 @@
 
   void test_isSubtypeOf_normalAndPositionalArgs_2() {
     // (a, [a]) -> void <: (a) -> void
-    ClassElement a = ElementFactory.classElement2("A");
+    ClassElement a = class_(name: 'A');
     FunctionType t = ElementFactory.functionElement6(
         "t", <ClassElement>[a], <ClassElement>[a]).type;
     FunctionType s =
@@ -1423,7 +1479,7 @@
 
   void test_isSubtypeOf_normalAndPositionalArgs_3() {
     // ([a]) -> void <: () -> void
-    ClassElement a = ElementFactory.classElement2("A");
+    ClassElement a = class_(name: 'A');
     FunctionType t =
         ElementFactory.functionElement6("t", null, <ClassElement>[a]).type;
     FunctionType s = ElementFactory.functionElement("s").type;
@@ -1433,7 +1489,7 @@
 
   void test_isSubtypeOf_normalAndPositionalArgs_4() {
     // (a, b, [c, d, e]) -> void <: (a, b, c, [d]) -> void
-    ClassElement a = ElementFactory.classElement2("A");
+    ClassElement a = class_(name: 'A');
     ClassElement b = ElementFactory.classElement2("B");
     ClassElement c = ElementFactory.classElement2("C");
     ClassElement d = ElementFactory.classElement2("D");
@@ -1450,8 +1506,8 @@
     // B extends A
     // (a) -> void <: (b) -> void
     // (b) -> void <: (a) -> void
-    ClassElement a = ElementFactory.classElement2("A");
-    ClassElement b = ElementFactory.classElement("B", a.type);
+    ClassElement a = class_(name: 'A');
+    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
     FunctionType t =
         ElementFactory.functionElement5("t", <ClassElement>[a]).type;
     FunctionType s =
@@ -1462,8 +1518,9 @@
 
   void test_isSubtypeOf_normalParameters_isNotAssignable() {
     // ! (a) -> void <: (b) -> void
-    FunctionType t = ElementFactory.functionElement5(
-        "t", <ClassElement>[ElementFactory.classElement2("A")]).type;
+    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);
@@ -1472,8 +1529,8 @@
   void test_isSubtypeOf_normalParameters_sHasMoreParams() {
     // B extends A
     // ! (a) -> void <: (b, b) -> void
-    ClassElement a = ElementFactory.classElement2("A");
-    ClassElement b = ElementFactory.classElement("B", a.type);
+    ClassElement a = class_(name: 'A');
+    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
     FunctionType t =
         ElementFactory.functionElement5("t", <ClassElement>[a]).type;
     FunctionType s =
@@ -1484,8 +1541,8 @@
   void test_isSubtypeOf_normalParameters_tHasMoreParams() {
     // B extends A
     // ! (a, a) -> void <: (a) -> void
-    ClassElement a = ElementFactory.classElement2("A");
-    ClassElement b = ElementFactory.classElement("B", a.type);
+    ClassElement a = class_(name: 'A');
+    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
     FunctionType t =
         ElementFactory.functionElement5("t", <ClassElement>[a, a]).type;
     FunctionType s =
@@ -1499,7 +1556,7 @@
   void test_isSubtypeOf_Object() {
     // () -> void <: Object
     FunctionType f = ElementFactory.functionElement("f").type;
-    InterfaceType t = ElementFactory.object.type;
+    InterfaceType t = typeProvider.objectType;
     expect(f.isSubtypeOf(t), isTrue);
   }
 
@@ -1507,8 +1564,8 @@
     // B extends A
     // ([a]) -> void <: ([b]) -> void
     // ([b]) -> void <: ([a]) -> void
-    ClassElement a = ElementFactory.classElement2("A");
-    ClassElement b = ElementFactory.classElement("B", a.type);
+    ClassElement a = class_(name: 'A');
+    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
     FunctionType t =
         ElementFactory.functionElement6("t", null, <ClassElement>[a]).type;
     FunctionType s =
@@ -1520,7 +1577,7 @@
   void test_isSubtypeOf_positionalParameters_isNotAssignable() {
     // ! ([a]) -> void <: ([b]) -> void
     FunctionType t = ElementFactory.functionElement6(
-        "t", null, <ClassElement>[ElementFactory.classElement2("A")]).type;
+        "t", null, <ClassElement>[class_(name: 'A')]).type;
     FunctionType s = ElementFactory.functionElement6(
         "s", null, <ClassElement>[ElementFactory.classElement2("B")]).type;
     expect(t.isSubtypeOf(s), isFalse);
@@ -1529,8 +1586,8 @@
   void test_isSubtypeOf_positionalParameters_sHasMoreParams() {
     // B extends A
     // ! ([a]) -> void <: ([b, b]) -> void
-    ClassElement a = ElementFactory.classElement2("A");
-    ClassElement b = ElementFactory.classElement("B", a.type);
+    ClassElement a = class_(name: 'A');
+    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
     FunctionType t =
         ElementFactory.functionElement6("t", null, <ClassElement>[a]).type;
     FunctionType s =
@@ -1541,8 +1598,8 @@
   void test_isSubtypeOf_positionalParameters_tHasMoreParams() {
     // B extends A
     // ([a, a]) -> void <: ([b]) -> void
-    ClassElement a = ElementFactory.classElement2("A");
-    ClassElement b = ElementFactory.classElement("B", a.type);
+    ClassElement a = class_(name: 'A');
+    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
     FunctionType t =
         ElementFactory.functionElement6("t", null, <ClassElement>[a, a]).type;
     FunctionType s =
@@ -1563,10 +1620,12 @@
     // B extends A
     // () -> A <: () -> B
     // () -> B <: () -> A
-    ClassElement a = ElementFactory.classElement2("A");
-    ClassElement b = ElementFactory.classElement("B", a.type);
-    FunctionType t = ElementFactory.functionElement2("t", a.type).type;
-    FunctionType s = ElementFactory.functionElement2("s", b.type).type;
+    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);
   }
@@ -1574,11 +1633,11 @@
   void test_isSubtypeOf_returnType_tNotAssignableToS() {
     // ! () -> A <: () -> B
     FunctionType t = ElementFactory.functionElement2(
-            "t", ElementFactory.classElement2("A").type)
+            "t", interfaceType(ElementFactory.classElement2('A')))
         .type;
-    FunctionType s = ElementFactory.functionElement2(
-            "s", ElementFactory.classElement2("B").type)
-        .type;
+    FunctionType s =
+        ElementFactory.functionElement2("s", interfaceType(class_(name: 'B')))
+            .type;
     expect(t.isSubtypeOf(s), isFalse);
   }
 
@@ -1619,7 +1678,7 @@
   void test_isSubtypeOf_wrongFunctionType_normal_named() {
     // ! (a) -> void <: ({name: A}) -> void
     // ! ({name: A}) -> void <: (a) -> void
-    ClassElement a = ElementFactory.classElement2("A");
+    ClassElement a = class_(name: 'A');
     FunctionType t =
         ElementFactory.functionElement5("t", <ClassElement>[a]).type;
     FunctionType s = ElementFactory.functionElement7(
@@ -1631,7 +1690,7 @@
   void test_isSubtypeOf_wrongFunctionType_optional_named() {
     // ! ([a]) -> void <: ({name: A}) -> void
     // ! ({name: A}) -> void <: ([a]) -> void
-    ClassElement a = ElementFactory.classElement2("A");
+    ClassElement a = class_(name: 'A');
     FunctionType t =
         ElementFactory.functionElement6("t", null, <ClassElement>[a]).type;
     FunctionType s = ElementFactory.functionElement7(
@@ -1643,8 +1702,11 @@
   void test_namedParameterTypes_pruned_no_type_arguments() {
     var f = ElementFactory.genericTypeAliasElement('f');
     var g = ElementFactory.genericTypeAliasElement('g');
-    f.function.parameters = [ElementFactory.namedParameter2('x', g.type)];
-    FunctionTypeImpl paramType = f.type.namedParameterTypes['x'];
+    f.function.parameters = [
+      ElementFactory.namedParameter2('x', functionTypeAliasType(g))
+    ];
+    FunctionTypeImpl paramType =
+        functionTypeAliasType(f).namedParameterTypes['x'];
     expect(paramType.prunedTypedefs, hasLength(1));
     expect(paramType.prunedTypedefs[0], same(f));
   }
@@ -1653,15 +1715,19 @@
     var f = ElementFactory.genericTypeAliasElement('f');
     var g = ElementFactory.genericTypeAliasElement('g');
     f.typeParameters = [ElementFactory.typeParameterElement('T')];
-    f.function.parameters = [ElementFactory.namedParameter2('x', g.type)];
-    FunctionTypeImpl paramType = f.type.namedParameterTypes['x'];
+    f.function.parameters = [
+      ElementFactory.namedParameter2('x', functionTypeAliasType(g))
+    ];
+    FunctionTypeImpl paramType =
+        functionTypeAliasType(f, typeArguments: [typeProvider.intType])
+            .namedParameterTypes['x'];
     expect(paramType.prunedTypedefs, hasLength(1));
     expect(paramType.prunedTypedefs[0], same(f));
   }
 
   void test_newPrune_no_previous_prune() {
     var f = ElementFactory.genericTypeAliasElement('f');
-    FunctionTypeImpl type = f.type;
+    FunctionTypeImpl type = functionTypeAliasType(f);
     List<FunctionTypeAliasElement> pruneList = type.newPrune;
     expect(pruneList, hasLength(1));
     expect(pruneList[0], same(f));
@@ -1683,14 +1749,14 @@
     // the user (and hence can't participate in circularities).
     var f = ElementFactory.genericTypeAliasElement('f');
     f.isSynthetic = true;
-    FunctionTypeImpl type = f.type;
+    FunctionTypeImpl type = functionTypeAliasType(f);
     expect(type.newPrune, isNull);
   }
 
   void test_newPrune_with_previous_prune() {
     var f = ElementFactory.genericTypeAliasElement('f');
     var g = ElementFactory.genericTypeAliasElement('g');
-    FunctionTypeImpl type = f.type;
+    FunctionTypeImpl type = functionTypeAliasType(f);
     FunctionTypeImpl prunedType = type.pruned([g]);
     List<FunctionTypeAliasElement> pruneList = prunedType.newPrune;
     expect(pruneList, hasLength(2));
@@ -1701,8 +1767,11 @@
   void test_normalParameterTypes_pruned_no_type_arguments() {
     var f = ElementFactory.genericTypeAliasElement('f');
     var g = ElementFactory.genericTypeAliasElement('g');
-    f.function.parameters = [ElementFactory.requiredParameter2('x', g.type)];
-    FunctionTypeImpl paramType = f.type.normalParameterTypes[0];
+    f.function.parameters = [
+      ElementFactory.requiredParameter2('x', functionTypeAliasType(g))
+    ];
+    FunctionTypeImpl paramType =
+        functionTypeAliasType(f).normalParameterTypes[0];
     expect(paramType.prunedTypedefs, hasLength(1));
     expect(paramType.prunedTypedefs[0], same(f));
   }
@@ -1711,8 +1780,12 @@
     var f = ElementFactory.genericTypeAliasElement('f');
     var g = ElementFactory.genericTypeAliasElement('g');
     f.typeParameters = [ElementFactory.typeParameterElement('T')];
-    f.function.parameters = [ElementFactory.requiredParameter2('x', g.type)];
-    FunctionTypeImpl paramType = f.type.normalParameterTypes[0];
+    f.function.parameters = [
+      ElementFactory.requiredParameter2('x', functionTypeAliasType(g))
+    ];
+    FunctionTypeImpl paramType =
+        functionTypeAliasType(f, typeArguments: [typeProvider.intType])
+            .normalParameterTypes[0];
     expect(paramType.prunedTypedefs, hasLength(1));
     expect(paramType.prunedTypedefs[0], same(f));
   }
@@ -1720,8 +1793,11 @@
   void test_optionalParameterTypes_pruned_no_type_arguments() {
     var f = ElementFactory.genericTypeAliasElement('f');
     var g = ElementFactory.genericTypeAliasElement('g');
-    f.function.parameters = [ElementFactory.positionalParameter2('x', g.type)];
-    FunctionTypeImpl paramType = f.type.optionalParameterTypes[0];
+    f.function.parameters = [
+      ElementFactory.positionalParameter2('x', functionTypeAliasType(g))
+    ];
+    FunctionTypeImpl paramType =
+        functionTypeAliasType(f).optionalParameterTypes[0];
     expect(paramType.prunedTypedefs, hasLength(1));
     expect(paramType.prunedTypedefs[0], same(f));
   }
@@ -1730,8 +1806,12 @@
     var f = ElementFactory.genericTypeAliasElement('f');
     var g = ElementFactory.genericTypeAliasElement('g');
     f.typeParameters = [ElementFactory.typeParameterElement('T')];
-    f.function.parameters = [ElementFactory.positionalParameter2('x', g.type)];
-    FunctionTypeImpl paramType = f.type.optionalParameterTypes[0];
+    f.function.parameters = [
+      ElementFactory.positionalParameter2('x', functionTypeAliasType(g))
+    ];
+    FunctionTypeImpl paramType =
+        functionTypeAliasType(f, typeArguments: [typeProvider.intType])
+            .optionalParameterTypes[0];
     expect(paramType.prunedTypedefs, hasLength(1));
     expect(paramType.prunedTypedefs[0], same(f));
   }
@@ -1747,8 +1827,8 @@
   void test_returnType_pruned_no_type_arguments() {
     var f = ElementFactory.genericTypeAliasElement('f');
     var g = ElementFactory.genericTypeAliasElement('g');
-    f.function.returnType = g.type;
-    FunctionTypeImpl paramType = f.type.returnType;
+    f.function.returnType = functionTypeAliasType(g);
+    FunctionTypeImpl paramType = functionTypeAliasType(f).returnType;
     expect(paramType.prunedTypedefs, hasLength(1));
     expect(paramType.prunedTypedefs[0], same(f));
   }
@@ -1757,15 +1837,18 @@
     var f = ElementFactory.genericTypeAliasElement('f');
     var g = ElementFactory.genericTypeAliasElement('g');
     f.typeParameters = [ElementFactory.typeParameterElement('T')];
-    f.function.returnType = g.type;
-    FunctionTypeImpl paramType = f.type.returnType;
+    f.function.returnType = functionTypeAliasType(g);
+    FunctionTypeImpl paramType =
+        functionTypeAliasType(f, typeArguments: [typeProvider.intType])
+            .returnType;
     expect(paramType.prunedTypedefs, hasLength(1));
     expect(paramType.prunedTypedefs[0], same(f));
   }
 
   void test_substitute2_equal() {
     ClassElementImpl definingClass = ElementFactory.classElement2("C", ["E"]);
-    TypeParameterType parameterType = definingClass.typeParameters[0].type;
+    TypeParameterType parameterType =
+        typeParameterType(definingClass.typeParameters[0]);
     MethodElementImpl functionElement =
         new MethodElementImpl.forNode(AstTestFactory.identifier3("m"));
     String namedParameterName = "c";
@@ -1833,16 +1916,19 @@
   void test_toString_recursive() {
     var t = ElementFactory.genericTypeAliasElement("t");
     var s = ElementFactory.genericTypeAliasElement("s");
-    t.function.returnType = s.type;
-    s.function.returnType = t.type;
-    expect(t.type.toString(), '... Function() Function()');
+    t.function.returnType = functionTypeAliasType(s);
+    s.function.returnType = functionTypeAliasType(t);
+    expect(functionTypeAliasType(t).toString(), '... Function() Function()');
   }
 
   void test_toString_recursive_via_interface_type() {
     var f = ElementFactory.genericTypeAliasElement('f');
     ClassElementImpl c = ElementFactory.classElement2('C', ['T']);
-    f.function.returnType = c.type.instantiate([f.type]);
-    expect(f.type.toString(), 'C<...> Function()');
+    f.function.returnType = c.instantiate(
+      typeArguments: [functionTypeAliasType(f)],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+    expect(functionTypeAliasType(f).toString(), 'C<...> Function()');
   }
 
   void test_typeParameters_genericLocalFunction_genericMethod_genericClass() {
@@ -1863,7 +1949,7 @@
     FunctionElementImpl function = ElementFactory.functionElement('f');
     function.enclosingElement = method;
     function.typeParameters = ElementFactory.typeParameters(['U']);
-    function.returnType = function.typeParameters[0].type;
+    function.returnType = typeParameterType(function.typeParameters[0]);
     function.type = new FunctionTypeImpl(function);
 
     List<TypeParameterElement> inheritedParameters = <TypeParameterElement>[];
@@ -1902,7 +1988,7 @@
     //   Object m<T>() => null;
     // }
     //
-    ClassElementImpl classElement = ElementFactory.classElement2('C');
+    ClassElementImpl classElement = class_(name: 'C');
     MethodElementImpl method = new MethodElementImpl('m', 0);
     method.enclosingElement = classElement;
     method.returnType = ElementFactory.objectType;
@@ -1957,7 +2043,7 @@
     //   Object m<T>() => null;
     // }
     //
-    ClassElementImpl classElement = ElementFactory.classElement2('C');
+    ClassElementImpl classElement = class_(name: 'C');
     MethodElementImpl method = new MethodElementImpl('m', 0);
     method.enclosingElement = classElement;
     method.typeParameters = ElementFactory.typeParameters(['T']);
@@ -1977,68 +2063,85 @@
         new MethodElementImpl.forNode(AstTestFactory.identifier3("m"));
     enclosingClass.methods = <MethodElement>[methodElement];
     FunctionTypeImpl type = new FunctionTypeImpl(methodElement);
-    DartType expectedType = enclosingClass.typeParameters[0].type;
+    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) => element.type);
+    return typeParameters
+        .map((TypeParameterElement element) => typeParameterType(element));
   }
 }
 
 @reflectiveTest
-class InterfaceTypeImplTest extends EngineTestCase {
-  /**
-   * The type provider used to access the types.
-   */
-  TestTypeProvider _typeProvider;
-
-  @override
-  void setUp() {
-    super.setUp();
-    _typeProvider = new TestTypeProvider();
-  }
-
+class InterfaceTypeImplTest extends AbstractTypeTest {
   test_asInstanceOf_explicitGeneric() {
     // class A<E> {}
     // class B implements A<C> {}
     // class C {}
-    ClassElementImpl classA = ElementFactory.classElement2('A', ['E']);
-    ClassElementImpl classB = ElementFactory.classElement2('B');
-    ClassElementImpl classC = ElementFactory.classElement2('C');
-    classB.interfaces = <InterfaceType>[
-      classA.type.instantiate([classC.type])
-    ];
+    var A = class_(name: 'A', typeParameters: [
+      typeParameter('E'),
+    ]);
+    var B = class_(name: 'B');
+    var C = class_(name: 'C');
 
-    InterfaceTypeImpl targetType = classB.type as InterfaceTypeImpl;
-    InterfaceType result = targetType.asInstanceOf(classA);
-    expect(result, classA.type.instantiate([classC.type]));
+    var AofC = A.instantiate(
+      typeArguments: [
+        interfaceType(C),
+      ],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+
+    B.interfaces = <InterfaceType>[AofC];
+
+    InterfaceTypeImpl targetType = interfaceType(B);
+    InterfaceType result = targetType.asInstanceOf(A);
+    expect(result, AofC);
   }
 
   test_asInstanceOf_passThroughGeneric() {
     // class A<E> {}
     // class B<E> implements A<E> {}
-    ClassElementImpl classA = ElementFactory.classElement2('A', ['E']);
-    ClassElementImpl classB = ElementFactory.classElement2('B', ['E']);
-    ClassElementImpl classC = ElementFactory.classElement2('C');
-    classB.interfaces = <InterfaceType>[
-      classA.type.instantiate([classB.typeParameters[0].type])
-    ];
+    // class C {}
+    var AE = typeParameter('E');
+    var A = class_(name: 'A', typeParameters: [AE]);
 
-    InterfaceTypeImpl targetType =
-        classB.type.instantiate([classC.type]) as InterfaceTypeImpl;
-    InterfaceType result = targetType.asInstanceOf(classA);
-    expect(result, classA.type.instantiate([classC.type]));
+    var BE = typeParameter('E');
+    var B = class_(
+      name: 'B',
+      typeParameters: [BE],
+      interfaces: [
+        A.instantiate(
+          typeArguments: [typeParameterType(BE)],
+          nullabilitySuffix: NullabilitySuffix.star,
+        ),
+      ],
+    );
+
+    var C = class_(name: 'C');
+
+    InterfaceTypeImpl targetType = B.instantiate(
+      typeArguments: [interfaceType(C)],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+    InterfaceType result = targetType.asInstanceOf(A);
+    expect(
+      result,
+      A.instantiate(
+        typeArguments: [interfaceType(C)],
+        nullabilitySuffix: NullabilitySuffix.star,
+      ),
+    );
   }
 
   void test_creation() {
-    expect(new InterfaceTypeImpl(ElementFactory.classElement2("A")), isNotNull);
+    expect(new InterfaceTypeImpl(class_(name: 'A')), isNotNull);
   }
 
   void test_getAccessors() {
-    ClassElementImpl typeElement = ElementFactory.classElement2("A");
+    ClassElementImpl typeElement = class_(name: 'A');
     PropertyAccessorElement getterG =
         ElementFactory.getterElement("g", false, null);
     PropertyAccessorElement getterH =
@@ -2049,13 +2152,13 @@
   }
 
   void test_getAccessors_empty() {
-    ClassElementImpl typeElement = ElementFactory.classElement2("A");
+    ClassElementImpl typeElement = class_(name: 'A');
     InterfaceTypeImpl type = new InterfaceTypeImpl(typeElement);
     expect(type.accessors.length, 0);
   }
 
   void test_getConstructors() {
-    ClassElementImpl typeElement = ElementFactory.classElement2("A");
+    ClassElementImpl typeElement = class_(name: 'A');
     ConstructorElementImpl constructorOne =
         ElementFactory.constructorElement(typeElement, 'one', false);
     ConstructorElementImpl constructorTwo =
@@ -2069,14 +2172,14 @@
   }
 
   void test_getConstructors_empty() {
-    ClassElementImpl typeElement = ElementFactory.classElement2("A");
+    ClassElementImpl typeElement = class_(name: 'A');
     typeElement.constructors = const <ConstructorElement>[];
     InterfaceTypeImpl type = new InterfaceTypeImpl(typeElement);
     expect(type.constructors, isEmpty);
   }
 
   void test_getElement() {
-    ClassElementImpl typeElement = ElementFactory.classElement2("A");
+    ClassElementImpl typeElement = class_(name: 'A');
     InterfaceTypeImpl type = new InterfaceTypeImpl(typeElement);
     expect(type.element, typeElement);
   }
@@ -2085,12 +2188,12 @@
     //
     // class A { g {} }
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String getterName = "g";
     PropertyAccessorElement getterG =
         ElementFactory.getterElement(getterName, false, null);
     classA.accessors = <PropertyAccessorElement>[getterG];
-    InterfaceType typeA = classA.type;
+    InterfaceType typeA = interfaceType(classA);
     expect(typeA.getGetter(getterName), same(getterG));
   }
 
@@ -2098,31 +2201,36 @@
     //
     // class A<E> { E get g {} }
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A", ["E"]);
-    DartType typeE = classA.type.typeArguments[0];
+    var AE = typeParameter('E');
+    var A = class_(name: 'A', typeParameters: [AE]);
+
+    DartType typeAE = typeParameterType(AE);
     String getterName = "g";
     PropertyAccessorElementImpl getterG =
-        ElementFactory.getterElement(getterName, false, typeE);
-    classA.accessors = <PropertyAccessorElement>[getterG];
+        ElementFactory.getterElement(getterName, false, typeAE);
+    A.accessors = <PropertyAccessorElement>[getterG];
     getterG.type = new FunctionTypeImpl(getterG);
     //
     // A<I>
     //
-    InterfaceType typeI = ElementFactory.classElement2("I").type;
-    InterfaceTypeImpl typeAI = new InterfaceTypeImpl(classA);
-    typeAI.typeArguments = <DartType>[typeI];
-    PropertyAccessorElement getter = typeAI.getGetter(getterName);
+    InterfaceType I = interfaceType(class_(name: 'I'));
+    InterfaceTypeImpl AofI = A.instantiate(
+      typeArguments: [I],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+
+    PropertyAccessorElement getter = AofI.getGetter(getterName);
     expect(getter, isNotNull);
     FunctionType getterType = getter.type;
-    expect(getterType.returnType, same(typeI));
+    expect(getterType.returnType, same(I));
   }
 
   void test_getGetter_unimplemented() {
     //
     // class A {}
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
+    var classA = class_(name: 'A');
+    InterfaceType typeA = interfaceType(classA);
     expect(typeA.getGetter("g"), isNull);
   }
 
@@ -2130,13 +2238,13 @@
     //
     // class C implements A, B
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    InterfaceType typeB = classB.type;
-    ClassElementImpl classC = ElementFactory.classElement2("C");
+    var classA = class_(name: 'A');
+    InterfaceType typeA = interfaceType(classA);
+    var classB = ElementFactory.classElement2("B");
+    InterfaceType typeB = interfaceType(classB);
+    var classC = ElementFactory.classElement2("C");
     classC.interfaces = <InterfaceType>[typeA, typeB];
-    List<InterfaceType> interfaces = classC.type.interfaces;
+    List<InterfaceType> interfaces = interfaceType(classC).interfaces;
     expect(interfaces, hasLength(2));
     if (identical(interfaces[0], typeA)) {
       expect(interfaces[1], same(typeB));
@@ -2151,22 +2259,29 @@
     // class A<E>
     // class B<F> implements A<F>
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A", ["E"]);
-    ClassElementImpl classB = ElementFactory.classElement2("B", ["F"]);
-    InterfaceType typeB = classB.type;
-    InterfaceTypeImpl typeAF = new InterfaceTypeImpl(classA);
-    typeAF.typeArguments = <DartType>[typeB.typeArguments[0]];
-    classB.interfaces = <InterfaceType>[typeAF];
+    var E = typeParameter('E');
+    var A = class_(name: 'A', typeParameters: [E]);
+    var F = typeParameter('F');
+    var B = class_(
+      name: 'B',
+      typeParameters: [F],
+      interfaces: [
+        A.instantiate(
+          typeArguments: [typeParameterType(F)],
+          nullabilitySuffix: NullabilitySuffix.star,
+        )
+      ],
+    );
     //
     // B<I>
     //
-    InterfaceType typeI = ElementFactory.classElement2("I").type;
-    InterfaceTypeImpl typeBI = new InterfaceTypeImpl(classB);
-    typeBI.typeArguments = <DartType>[typeI];
+    InterfaceType typeI = interfaceType(class_(name: 'I'));
+    InterfaceTypeImpl typeBI = interfaceType(B, typeArguments: [typeI]);
+
     List<InterfaceType> interfaces = typeBI.interfaces;
     expect(interfaces, hasLength(1));
     InterfaceType result = interfaces[0];
-    expect(result.element, same(classA));
+    expect(result.element, same(A));
     expect(result.typeArguments[0], same(typeI));
   }
 
@@ -2174,11 +2289,11 @@
     //
     // class A { m() {} }
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElementImpl methodM = ElementFactory.methodElement(methodName, null);
     classA.methods = <MethodElement>[methodM];
-    InterfaceType typeA = classA.type;
+    InterfaceType typeA = interfaceType(classA);
     expect(typeA.getMethod(methodName), same(methodM));
   }
 
@@ -2187,8 +2302,8 @@
     // class A<E> { B m() {} }
     // class B {}
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A", ["E"]);
-    InterfaceType typeB = ElementFactory.classElement2("B").type;
+    var classA = ElementFactory.classElement2("A", ["E"]);
+    InterfaceType typeB = interfaceType(class_(name: 'B'));
     String methodName = "m";
     MethodElementImpl methodM =
         ElementFactory.methodElement(methodName, typeB, []);
@@ -2197,7 +2312,7 @@
     //
     // A<I>
     //
-    InterfaceType typeI = ElementFactory.classElement2("I").type;
+    InterfaceType typeI = interfaceType(class_(name: 'I'));
     InterfaceTypeImpl typeAI = new InterfaceTypeImpl(classA);
     typeAI.typeArguments = <DartType>[typeI];
     MethodElement method = typeAI.getMethod(methodName);
@@ -2211,24 +2326,25 @@
     //
     // class A<E> { E m(E p) {} }
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A", ["E"]);
-    DartType typeE = classA.type.typeArguments[0];
+    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]);
-    classA.methods = <MethodElement>[methodM];
+    A.methods = <MethodElement>[methodM];
     methodM.type = new FunctionTypeImpl(methodM);
     //
     // A<I>
     //
-    InterfaceType typeI = ElementFactory.classElement2("I").type;
-    InterfaceTypeImpl typeAI = new InterfaceTypeImpl(classA);
+    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.
-    classA.version++;
+    A.version++;
     expect(typeAI.methods.single, isNot(same(method)));
   }
 
@@ -2236,18 +2352,19 @@
     //
     // class A<E> { E m(E p) {} }
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A", ["E"]);
-    DartType typeE = classA.type.typeArguments[0];
+    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]);
-    classA.methods = <MethodElement>[methodM];
+    A.methods = <MethodElement>[methodM];
     methodM.type = new FunctionTypeImpl(methodM);
     //
     // A<I>
     //
-    InterfaceType typeI = ElementFactory.classElement2("I").type;
-    InterfaceTypeImpl typeAI = new InterfaceTypeImpl(classA);
+    InterfaceType typeI = interfaceType(class_(name: 'I'));
+    InterfaceTypeImpl typeAI = new InterfaceTypeImpl(A);
     typeAI.typeArguments = <DartType>[typeI];
     MethodElement method = typeAI.getMethod(methodName);
     expect(method, isNotNull);
@@ -2264,13 +2381,13 @@
     //
     // class A {}
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
+    var classA = class_(name: 'A');
+    InterfaceType typeA = interfaceType(classA);
     expect(typeA.getMethod("m"), isNull);
   }
 
   void test_getMethods() {
-    ClassElementImpl typeElement = ElementFactory.classElement2("A");
+    ClassElementImpl typeElement = class_(name: 'A');
     MethodElementImpl methodOne = ElementFactory.methodElement("one", null);
     MethodElementImpl methodTwo = ElementFactory.methodElement("two", null);
     typeElement.methods = <MethodElement>[methodOne, methodTwo];
@@ -2279,7 +2396,7 @@
   }
 
   void test_getMethods_empty() {
-    ClassElementImpl typeElement = ElementFactory.classElement2("A");
+    ClassElementImpl typeElement = class_(name: 'A');
     InterfaceTypeImpl type = new InterfaceTypeImpl(typeElement);
     expect(type.methods.length, 0);
   }
@@ -2288,13 +2405,13 @@
     //
     // class C extends Object with A, B
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    InterfaceType typeB = classB.type;
-    ClassElementImpl classC = ElementFactory.classElement2("C");
+    var classA = class_(name: 'A');
+    InterfaceType typeA = interfaceType(classA);
+    var classB = ElementFactory.classElement2("B");
+    InterfaceType typeB = interfaceType(classB);
+    var classC = ElementFactory.classElement2("C");
     classC.mixins = <InterfaceType>[typeA, typeB];
-    List<InterfaceType> interfaces = classC.type.mixins;
+    List<InterfaceType> interfaces = interfaceType(classC).mixins;
     expect(interfaces, hasLength(2));
     if (identical(interfaces[0], typeA)) {
       expect(interfaces[1], same(typeB));
@@ -2309,22 +2426,29 @@
     // class A<E>
     // class B<F> extends Object with A<F>
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A", ["E"]);
-    ClassElementImpl classB = ElementFactory.classElement2("B", ["F"]);
-    InterfaceType typeB = classB.type;
-    InterfaceTypeImpl typeAF = new InterfaceTypeImpl(classA);
-    typeAF.typeArguments = <DartType>[typeB.typeArguments[0]];
-    classB.mixins = <InterfaceType>[typeAF];
+    var E = typeParameter('E');
+    var A = class_(name: 'A', typeParameters: [E]);
+
+    var F = typeParameter('F');
+    var B = class_(
+      name: 'B',
+      typeParameters: [F],
+      mixins: [
+        interfaceType(A, typeArguments: [
+          typeParameterType(F),
+        ]),
+      ],
+    );
     //
     // B<I>
     //
-    InterfaceType typeI = ElementFactory.classElement2("I").type;
-    InterfaceTypeImpl typeBI = new InterfaceTypeImpl(classB);
+    InterfaceType typeI = interfaceType(class_(name: 'I'));
+    InterfaceTypeImpl typeBI = new InterfaceTypeImpl(B);
     typeBI.typeArguments = <DartType>[typeI];
     List<InterfaceType> interfaces = typeBI.mixins;
     expect(interfaces, hasLength(1));
     InterfaceType result = interfaces[0];
-    expect(result.element, same(classA));
+    expect(result.element, same(A));
     expect(result.typeArguments[0], same(typeI));
   }
 
@@ -2332,12 +2456,12 @@
     //
     // class A { s() {} }
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String setterName = "s";
     PropertyAccessorElement setterS =
         ElementFactory.setterElement(setterName, false, null);
     classA.accessors = <PropertyAccessorElement>[setterS];
-    InterfaceType typeA = classA.type;
+    InterfaceType typeA = interfaceType(classA);
     expect(typeA.getSetter(setterName), same(setterS));
   }
 
@@ -2345,18 +2469,19 @@
     //
     // class A<E> { set s(E p) {} }
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A", ["E"]);
-    DartType typeE = classA.type.typeArguments[0];
+    var E = typeParameter('E');
+    var A = class_(name: 'A', typeParameters: [E]);
+    DartType typeE = typeParameterType(E);
     String setterName = "s";
     PropertyAccessorElementImpl setterS =
         ElementFactory.setterElement(setterName, false, typeE);
-    classA.accessors = <PropertyAccessorElement>[setterS];
+    A.accessors = <PropertyAccessorElement>[setterS];
     setterS.type = new FunctionTypeImpl(setterS);
     //
     // A<I>
     //
-    InterfaceType typeI = ElementFactory.classElement2("I").type;
-    InterfaceTypeImpl typeAI = new InterfaceTypeImpl(classA);
+    InterfaceType typeI = interfaceType(class_(name: 'I'));
+    InterfaceTypeImpl typeAI = new InterfaceTypeImpl(A);
     typeAI.typeArguments = <DartType>[typeI];
     PropertyAccessorElement setter = typeAI.getSetter(setterName);
     expect(setter, isNotNull);
@@ -2370,8 +2495,8 @@
     //
     // class A {}
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
+    var classA = class_(name: 'A');
+    InterfaceType typeA = interfaceType(classA);
     expect(typeA.getSetter("s"), isNull);
   }
 
@@ -2379,10 +2504,10 @@
     //
     // class B extends A
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
-    ClassElementImpl classB = ElementFactory.classElement("B", typeA);
-    InterfaceType typeB = classB.type;
+    var classA = class_(name: 'A');
+    InterfaceType typeA = interfaceType(classA);
+    var classB = ElementFactory.classElement("B", typeA);
+    InterfaceType typeB = interfaceType(classB);
     expect(typeB.superclass, same(typeA));
   }
 
@@ -2391,31 +2516,38 @@
     // class A<E>
     // class B<F> extends A<F>
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A", ["E"]);
-    ClassElementImpl classB = ElementFactory.classElement2("B", ["F"]);
-    InterfaceType typeB = classB.type;
-    InterfaceTypeImpl typeAF = new InterfaceTypeImpl(classA);
-    typeAF.typeArguments = <DartType>[typeB.typeArguments[0]];
-    classB.supertype = typeAF;
+    var E = typeParameter('E');
+    var A = class_(name: 'A', typeParameters: [E]);
+
+    var F = typeParameter('F');
+    var typeF = typeParameterType(F);
+
+    var B = class_(
+      name: 'B',
+      typeParameters: [F],
+      superType: interfaceType(A, typeArguments: [typeF]),
+    );
+
+    var classB = B;
     //
     // B<I>
     //
-    InterfaceType typeI = ElementFactory.classElement2("I").type;
+    InterfaceType typeI = interfaceType(class_(name: 'I'));
     InterfaceTypeImpl typeBI = new InterfaceTypeImpl(classB);
     typeBI.typeArguments = <DartType>[typeI];
     InterfaceType superclass = typeBI.superclass;
-    expect(superclass.element, same(classA));
+    expect(superclass.element, same(A));
     expect(superclass.typeArguments[0], same(typeI));
   }
 
   void test_getTypeArguments_empty() {
-    InterfaceType type = ElementFactory.classElement2("A").type;
+    InterfaceType type = interfaceType(ElementFactory.classElement2('A'));
     expect(type.typeArguments, hasLength(0));
   }
 
   void test_hashCode() {
-    ClassElement classA = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
+    ClassElement classA = class_(name: 'A');
+    InterfaceType typeA = interfaceType(classA);
     expect(0 == typeA.hashCode, isFalse);
   }
 
@@ -2432,9 +2564,13 @@
     ClassElement classA = ElementFactory.classElement2("A", ["E"]);
     ClassElement classB = ElementFactory.classElement2("B", ["F", "G"]);
     InterfaceTypeImpl typeAF = new InterfaceTypeImpl(classA);
-    typeAF.typeArguments = <DartType>[classB.typeParameters[0].type];
+    typeAF.typeArguments = <DartType>[
+      typeParameterType(classB.typeParameters[0])
+    ];
     InterfaceTypeImpl typeAG = new InterfaceTypeImpl(classA);
-    typeAG.typeArguments = <DartType>[classB.typeParameters[1].type];
+    typeAG.typeArguments = <DartType>[
+      typeParameterType(classB.typeParameters[1])
+    ];
     expect(typeAG.isAssignableTo(typeAF), isFalse);
   }
 
@@ -2444,66 +2580,70 @@
   }
 
   void test_isDirectSupertypeOf_extends() {
-    ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classB = ElementFactory.classElement("B", classA.type);
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
+    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 = ElementFactory.classElement2("A");
+    ClassElement classA = class_(name: 'A');
     ClassElement classB = ElementFactory.classElement2("B");
-    ClassElement classC = ElementFactory.classElement("C", classB.type);
-    InterfaceType typeA = classA.type;
-    InterfaceType typeC = classC.type;
+    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() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
+    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() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
+    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 = ElementFactory.classElement2("A").type;
+    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", classI.type);
+    ClassElement classJ =
+        ElementFactory.classElement("J", interfaceType(classI));
     InterfaceTypeImpl typeAI = new InterfaceTypeImpl(classA);
     InterfaceTypeImpl typeAJ = new InterfaceTypeImpl(classA);
-    typeAI.typeArguments = <DartType>[classI.type];
-    typeAJ.typeArguments = <DartType>[classJ.type];
+    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 = ElementFactory.classElement2("A");
-    ClassElement classB = ElementFactory.classElement("B", classA.type);
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
+    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()
@@ -2512,26 +2652,35 @@
   }
 
   void test_isMoreSpecificThan_dynamic() {
-    InterfaceType type = ElementFactory.classElement2("A").type;
+    InterfaceType type = interfaceType(ElementFactory.classElement2('A'));
     // ignore: deprecated_member_use_from_same_package
     expect(type.isMoreSpecificThan(DynamicTypeImpl.instance), isTrue);
   }
 
   void test_isMoreSpecificThan_generic() {
-    ClassElement classA = ElementFactory.classElement2("A", ["E"]);
-    ClassElement classB = ElementFactory.classElement2("B");
-    DartType dynamicType = DynamicTypeImpl.instance;
-    InterfaceType typeAOfDynamic =
-        classA.type.instantiate(<DartType>[dynamicType]);
-    InterfaceType typeAOfB = classA.type.instantiate(<DartType>[classB.type]);
+    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(typeAOfDynamic.isMoreSpecificThan(typeAOfB), isFalse);
+    expect(AofDynamic.isMoreSpecificThan(AofB), isFalse);
     // ignore: deprecated_member_use_from_same_package
-    expect(typeAOfB.isMoreSpecificThan(typeAOfDynamic), isTrue);
+    expect(AofB.isMoreSpecificThan(AofDynamic), isTrue);
   }
 
   void test_isMoreSpecificThan_self() {
-    InterfaceType type = ElementFactory.classElement2("A").type;
+    InterfaceType type = interfaceType(ElementFactory.classElement2('A'));
     // ignore: deprecated_member_use_from_same_package
     expect(type.isMoreSpecificThan(type), isTrue);
   }
@@ -2542,12 +2691,13 @@
     //  class B extends A {}
     //  class C implements B {}
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement2("C");
-    classC.interfaces = <InterfaceType>[classB.type];
-    InterfaceType typeA = classA.type;
-    InterfaceType typeC = classC.type;
+    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);
   }
@@ -2558,12 +2708,13 @@
     //  class B extends A {}
     //  class C with B {}
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement2("C");
-    classC.mixins = <InterfaceType>[classB.type];
-    InterfaceType typeA = classA.type;
-    InterfaceType typeC = classC.type;
+    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);
   }
@@ -2574,12 +2725,13 @@
     //  class B extends A {}
     //  class C {}
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement2("C");
-    InterfaceType typeA = classA.type;
-    InterfaceType typeC = classC.type;
-    classA.supertype = classB.type;
+    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);
   }
@@ -2590,11 +2742,13 @@
     //  class B extends A {}
     //  class C extends B {}
     //
-    ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classB = ElementFactory.classElement("B", classA.type);
-    ClassElement classC = ElementFactory.classElement("C", classB.type);
-    InterfaceType typeA = classA.type;
-    InterfaceType typeC = classC.type;
+    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);
   }
@@ -2604,8 +2758,9 @@
     // class A<E> {}
     //
     ClassElement classA = ElementFactory.classElement2("A", ["E"]);
-    InterfaceType typeA = classA.type;
-    TypeParameterType parameterType = classA.typeParameters[0].type;
+    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);
@@ -2618,31 +2773,31 @@
     // class A {}
     // class B<E extends A> {}
     //
-    ClassElement classA = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
-    ClassElementImpl classB = ElementFactory.classElement2("B");
+    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;
-    parameterEA.type = parameterAEType;
     classB.typeParameters = <TypeParameterElementImpl>[parameterEA];
     // ignore: deprecated_member_use_from_same_package
     expect(parameterAEType.isMoreSpecificThan(typeA), isTrue);
   }
 
   void test_isSubtypeOf_directSubtype() {
-    ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classB = ElementFactory.classElement("B", classA.type);
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
+    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 = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
+    ClassElement classA = class_(name: 'A');
+    InterfaceType typeA = interfaceType(classA);
     DartType dynamicType = DynamicTypeImpl.instance;
     expect(dynamicType.isSubtypeOf(typeA), isTrue);
     expect(typeA.isSubtypeOf(dynamicType), isTrue);
@@ -2656,35 +2811,37 @@
     // }
     //
     InterfaceType stringType = _typeProvider.stringType;
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     classA.methods = <MethodElement>[
       ElementFactory.methodElement("call", VoidTypeImpl.instance, [stringType])
     ];
     FunctionType functionType =
         ElementFactory.functionElement5("f", <ClassElement>[stringType.element])
             .type;
-    expect(classA.type.isSubtypeOf(functionType), isTrue);
+    expect(interfaceType(classA).isSubtypeOf(functionType), isTrue);
   }
 
   void test_isSubtypeOf_generic() {
-    ClassElement classA = ElementFactory.classElement2("A", ["E"]);
-    ClassElement classB = ElementFactory.classElement2("B");
+    ClassElement A = ElementFactory.classElement2("A", ["E"]);
+    ClassElement B = ElementFactory.classElement2("B");
     DartType dynamicType = DynamicTypeImpl.instance;
     InterfaceType typeAOfDynamic =
-        classA.type.instantiate(<DartType>[dynamicType]);
-    InterfaceType typeAOfB = classA.type.instantiate(<DartType>[classB.type]);
+        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 = ElementFactory.classElement2("A");
-    ClassElement classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement2("C");
+    ClassElement classA = class_(name: 'A');
+    ClassElement classB =
+        ElementFactory.classElement("B", interfaceType(classA));
+    var classC = ElementFactory.classElement2("C");
     InterfaceType typeObject = classA.supertype;
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
+    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);
@@ -2698,13 +2855,14 @@
     // class B extends A {}
     // class C with B {}
     //
-    ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement2("C");
+    ClassElement classA = class_(name: 'A');
+    ClassElement classB =
+        ElementFactory.classElement("B", interfaceType(classA));
+    var classC = ElementFactory.classElement2("C");
     InterfaceType typeObject = classA.supertype;
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
+    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);
@@ -2713,16 +2871,16 @@
   }
 
   void test_isSubtypeOf_object() {
-    ClassElement classA = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
+    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 = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
+    ClassElement classA = class_(name: 'A');
+    InterfaceType typeA = interfaceType(classA);
     expect(typeA.isSubtypeOf(typeA), isTrue);
   }
 
@@ -2732,21 +2890,24 @@
     //  class B extends A {}
     //  class C {}
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement2("C");
-    InterfaceType typeA = classA.type;
-    InterfaceType typeC = classC.type;
-    classA.supertype = classB.type;
+    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 = ElementFactory.classElement2("A");
-    ClassElement classB = ElementFactory.classElement("B", classA.type);
-    ClassElement classC = ElementFactory.classElement("C", classB.type);
-    InterfaceType typeA = classA.type;
-    InterfaceType typeC = classC.type;
+    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);
   }
@@ -2755,16 +2916,17 @@
     DartType dynamicType = DynamicTypeImpl.instance;
     ClassElement classA = ElementFactory.classElement2("A", ["E"]);
     ClassElement classI = ElementFactory.classElement2("I");
-    ClassElement classJ = ElementFactory.classElement("J", classI.type);
+    ClassElement classJ =
+        ElementFactory.classElement("J", interfaceType(classI));
     ClassElement classK = ElementFactory.classElement2("K");
-    InterfaceType typeA = classA.type;
-    InterfaceType typeA_dynamic = typeA.instantiate(<DartType>[dynamicType]);
+    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>[classI.type];
-    typeAJ.typeArguments = <DartType>[classJ.type];
-    typeAK.typeArguments = <DartType>[classK.type];
+    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);
@@ -2786,16 +2948,18 @@
     // class A<E> {}
     //
     ClassElement classA = ElementFactory.classElement2("A", ["E"]);
-    InterfaceType typeA = classA.type;
-    TypeParameterType parameterType = classA.typeParameters[0].type;
+    InterfaceType typeA = interfaceType(classA);
+    TypeParameterType parameterType =
+        typeParameterType(classA.typeParameters[0]);
     expect(typeA.isSubtypeOf(parameterType), isFalse);
   }
 
   void test_isSupertypeOf_directSupertype() {
-    ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classB = ElementFactory.classElement("B", classA.type);
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
+    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
@@ -2803,8 +2967,8 @@
   }
 
   void test_isSupertypeOf_dynamic() {
-    ClassElement classA = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
+    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);
@@ -2813,11 +2977,13 @@
   }
 
   void test_isSupertypeOf_indirectSupertype() {
-    ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classB = ElementFactory.classElement("B", classA.type);
-    ClassElement classC = ElementFactory.classElement("C", classB.type);
-    InterfaceType typeA = classA.type;
-    InterfaceType typeC = classC.type;
+    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
@@ -2825,13 +2991,14 @@
   }
 
   void test_isSupertypeOf_interface() {
-    ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement2("C");
+    ClassElement classA = class_(name: 'A');
+    ClassElement classB =
+        ElementFactory.classElement("B", interfaceType(classA));
+    var classC = ElementFactory.classElement2("C");
     InterfaceType typeObject = classA.supertype;
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
+    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);
@@ -2849,13 +3016,14 @@
     // class B extends A {}
     // class C with B {}
     //
-    ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classB = ElementFactory.classElement("B", classA.type);
-    ClassElementImpl classC = ElementFactory.classElement2("C");
+    ClassElement classA = class_(name: 'A');
+    ClassElement classB =
+        ElementFactory.classElement("B", interfaceType(classA));
+    var classC = ElementFactory.classElement2("C");
     InterfaceType typeObject = classA.supertype;
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
-    InterfaceType typeC = classC.type;
+    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);
@@ -2868,8 +3036,8 @@
   }
 
   void test_isSupertypeOf_object() {
-    ClassElement classA = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
+    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);
@@ -2878,8 +3046,8 @@
   }
 
   void test_isSupertypeOf_self() {
-    ClassElement classA = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
+    ClassElement classA = class_(name: 'A');
+    InterfaceType typeA = interfaceType(classA);
     // ignore: deprecated_member_use_from_same_package
     expect(typeA.isSupertypeOf(typeA), isTrue);
   }
@@ -2888,14 +3056,14 @@
     //
     // class A { g {} }
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String getterName = "g";
     PropertyAccessorElement getterG =
         ElementFactory.getterElement(getterName, false, null);
     classA.accessors = <PropertyAccessorElement>[getterG];
-    InterfaceType typeA = classA.type;
+    InterfaceType typeA = interfaceType(classA);
     LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+        ElementFactory.library(_analysisContext, "lib");
     CompilationUnitElement unit = library.definingCompilationUnit;
     (unit as CompilationUnitElementImpl).types = <ClassElement>[classA];
     expect(typeA.lookUpGetter(getterName, library), same(getterG));
@@ -2906,15 +3074,16 @@
     // class A { g {} }
     // class B extends A {}
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String getterName = "g";
     PropertyAccessorElement getterG =
         ElementFactory.getterElement(getterName, false, null);
     classA.accessors = <PropertyAccessorElement>[getterG];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    InterfaceType typeB = classB.type;
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
+    InterfaceType typeB = interfaceType(classB);
     LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+        ElementFactory.library(_analysisContext, "lib");
     CompilationUnitElement unit = library.definingCompilationUnit;
     (unit as CompilationUnitElementImpl).types = <ClassElement>[classA, classB];
     expect(typeB.lookUpGetter(getterName, library), same(getterG));
@@ -2929,7 +3098,7 @@
     //
     TestTypeProvider typeProvider = new TestTypeProvider();
     String getterName = 'g';
-    ClassElementImpl classB = ElementFactory.classElement2('B');
+    var classB = class_(name: 'B');
     ClassElementImpl classM1 = ElementFactory.classElement2('M1');
     PropertyAccessorElementImpl getterM1g = ElementFactory.getterElement(
         getterName, false, typeProvider.dynamicType);
@@ -2938,13 +3107,17 @@
     PropertyAccessorElementImpl getterM2g = ElementFactory.getterElement(
         getterName, false, typeProvider.dynamicType);
     classM2.accessors = <PropertyAccessorElement>[getterM2g];
-    ClassElementImpl classC = ElementFactory.classElement('C', classB.type);
-    classC.mixins = <InterfaceType>[classM1.type, classM2.type];
+    ClassElementImpl classC =
+        ElementFactory.classElement('C', interfaceType(classB));
+    classC.mixins = <InterfaceType>[
+      interfaceType(classM1),
+      interfaceType(classM2)
+    ];
     LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+        ElementFactory.library(_analysisContext, "lib");
     CompilationUnitElementImpl unit = library.definingCompilationUnit;
     unit.types = <ClassElement>[classB, classM1, classM2, classC];
-    expect(classC.type.lookUpGetter(getterName, library), getterM2g);
+    expect(interfaceType(classC).lookUpGetter(getterName, library), getterM2g);
   }
 
   void test_lookUpGetter_recursive() {
@@ -2952,12 +3125,12 @@
     // class A extends B {}
     // class B extends A {}
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
-    ClassElementImpl classB = ElementFactory.classElement("B", typeA);
-    classA.supertype = classB.type;
+    var classA = class_(name: 'A');
+    InterfaceType typeA = interfaceType(classA);
+    var classB = ElementFactory.classElement("B", typeA);
+    classA.supertype = interfaceType(classB);
     LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+        ElementFactory.library(_analysisContext, "lib");
     CompilationUnitElement unit = library.definingCompilationUnit;
     (unit as CompilationUnitElementImpl).types = <ClassElement>[classA, classB];
     expect(typeA.lookUpGetter("g", library), isNull);
@@ -2967,10 +3140,10 @@
     //
     // class A {}
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
+    var classA = class_(name: 'A');
+    InterfaceType typeA = interfaceType(classA);
     LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+        ElementFactory.library(_analysisContext, "lib");
     CompilationUnitElement unit = library.definingCompilationUnit;
     (unit as CompilationUnitElementImpl).types = <ClassElement>[classA];
     expect(typeA.lookUpGetter("g", library), isNull);
@@ -2980,13 +3153,13 @@
     //
     // class A { m() {} }
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElementImpl methodM = ElementFactory.methodElement(methodName, null);
     classA.methods = <MethodElement>[methodM];
-    InterfaceType typeA = classA.type;
+    InterfaceType typeA = interfaceType(classA);
     LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+        ElementFactory.library(_analysisContext, "lib");
     CompilationUnitElement unit = library.definingCompilationUnit;
     (unit as CompilationUnitElementImpl).types = <ClassElement>[classA];
     expect(typeA.lookUpMethod(methodName, library), same(methodM));
@@ -2997,14 +3170,15 @@
     // class A { m() {} }
     // class B extends A {}
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String methodName = "m";
     MethodElementImpl methodM = ElementFactory.methodElement(methodName, null);
     classA.methods = <MethodElement>[methodM];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    InterfaceType typeB = classB.type;
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
+    InterfaceType typeB = interfaceType(classB);
     LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+        ElementFactory.library(_analysisContext, "lib");
     CompilationUnitElement unit = library.definingCompilationUnit;
     (unit as CompilationUnitElementImpl).types = <ClassElement>[classA, classB];
     expect(typeB.lookUpMethod(methodName, library), same(methodM));
@@ -3018,7 +3192,7 @@
     // class C extends B with M1, M2 {}
     //
     String methodName = 'm';
-    ClassElementImpl classB = ElementFactory.classElement2('B');
+    var classB = class_(name: 'B');
     ClassElementImpl classM1 = ElementFactory.classElement2('M1');
     MethodElementImpl methodM1m =
         ElementFactory.methodElement(methodName, null);
@@ -3027,13 +3201,17 @@
     MethodElementImpl methodM2m =
         ElementFactory.methodElement(methodName, null);
     classM2.methods = <MethodElement>[methodM2m];
-    ClassElementImpl classC = ElementFactory.classElement('C', classB.type);
-    classC.mixins = <InterfaceType>[classM1.type, classM2.type];
+    ClassElementImpl classC =
+        ElementFactory.classElement('C', interfaceType(classB));
+    classC.mixins = <InterfaceType>[
+      interfaceType(classM1),
+      interfaceType(classM2)
+    ];
     LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+        ElementFactory.library(_analysisContext, "lib");
     CompilationUnitElementImpl unit = library.definingCompilationUnit;
     unit.types = <ClassElement>[classB, classM1, classM2, classC];
-    expect(classC.type.lookUpMethod(methodName, library), methodM2m);
+    expect(interfaceType(classC).lookUpMethod(methodName, library), methodM2m);
   }
 
   void test_lookUpMethod_parameterized() {
@@ -3041,27 +3219,32 @@
     // class A<E> { E m(E p) {} }
     // class B<F> extends A<F> {}
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A", ["E"]);
-    DartType typeE = classA.type.typeArguments[0];
+    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]);
-    classA.methods = <MethodElement>[methodM];
+    A.methods = <MethodElement>[methodM];
     methodM.type = new FunctionTypeImpl(methodM);
-    ClassElementImpl classB = ElementFactory.classElement2("B", ["F"]);
-    InterfaceType typeB = classB.type;
-    InterfaceTypeImpl typeAF = new InterfaceTypeImpl(classA);
-    typeAF.typeArguments = <DartType>[typeB.typeArguments[0]];
-    classB.supertype = typeAF;
+
+    var F = typeParameter('F');
+    var B = class_(
+      name: 'B',
+      typeParameters: [F],
+      superType: interfaceType(A, typeArguments: [
+        typeParameterType(F),
+      ]),
+    );
     LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+        ElementFactory.library(_analysisContext, "lib");
     CompilationUnitElement unit = library.definingCompilationUnit;
-    (unit as CompilationUnitElementImpl).types = <ClassElement>[classA];
+    (unit as CompilationUnitElementImpl).types = <ClassElement>[A];
     //
     // B<I>
     //
-    InterfaceType typeI = ElementFactory.classElement2("I").type;
-    InterfaceTypeImpl typeBI = new InterfaceTypeImpl(classB);
+    InterfaceType typeI = interfaceType(class_(name: 'I'));
+    InterfaceTypeImpl typeBI = new InterfaceTypeImpl(B);
     typeBI.typeArguments = <DartType>[typeI];
     MethodElement method = typeBI.lookUpMethod(methodName, library);
     expect(method, isNotNull);
@@ -3077,12 +3260,12 @@
     // class A extends B {}
     // class B extends A {}
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
-    ClassElementImpl classB = ElementFactory.classElement("B", typeA);
-    classA.supertype = classB.type;
+    var classA = class_(name: 'A');
+    InterfaceType typeA = interfaceType(classA);
+    var classB = ElementFactory.classElement("B", typeA);
+    classA.supertype = interfaceType(classB);
     LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+        ElementFactory.library(_analysisContext, "lib");
     CompilationUnitElement unit = library.definingCompilationUnit;
     (unit as CompilationUnitElementImpl).types = <ClassElement>[classA, classB];
     expect(typeA.lookUpMethod("m", library), isNull);
@@ -3092,10 +3275,10 @@
     //
     // class A {}
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
+    var classA = class_(name: 'A');
+    InterfaceType typeA = interfaceType(classA);
     LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+        ElementFactory.library(_analysisContext, "lib");
     CompilationUnitElement unit = library.definingCompilationUnit;
     (unit as CompilationUnitElementImpl).types = <ClassElement>[classA];
     expect(typeA.lookUpMethod("m", library), isNull);
@@ -3105,14 +3288,14 @@
     //
     // class A { s(x) {} }
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String setterName = "s";
     PropertyAccessorElement setterS =
         ElementFactory.setterElement(setterName, false, null);
     classA.accessors = <PropertyAccessorElement>[setterS];
-    InterfaceType typeA = classA.type;
+    InterfaceType typeA = interfaceType(classA);
     LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+        ElementFactory.library(_analysisContext, "lib");
     CompilationUnitElement unit = library.definingCompilationUnit;
     (unit as CompilationUnitElementImpl).types = <ClassElement>[classA];
     expect(typeA.lookUpSetter(setterName, library), same(setterS));
@@ -3123,15 +3306,16 @@
     // class A { s(x) {} }
     // class B extends A {}
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    var classA = class_(name: 'A');
     String setterName = "g";
     PropertyAccessorElement setterS =
         ElementFactory.setterElement(setterName, false, null);
     classA.accessors = <PropertyAccessorElement>[setterS];
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    InterfaceType typeB = classB.type;
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
+    InterfaceType typeB = interfaceType(classB);
     LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+        ElementFactory.library(_analysisContext, "lib");
     CompilationUnitElement unit = library.definingCompilationUnit;
     (unit as CompilationUnitElementImpl).types = <ClassElement>[classA, classB];
     expect(typeB.lookUpSetter(setterName, library), same(setterS));
@@ -3146,7 +3330,7 @@
     //
     TestTypeProvider typeProvider = new TestTypeProvider();
     String setterName = 's';
-    ClassElementImpl classB = ElementFactory.classElement2('B');
+    var classB = class_(name: 'B');
     ClassElementImpl classM1 = ElementFactory.classElement2('M1');
     PropertyAccessorElementImpl setterM1g = ElementFactory.setterElement(
         setterName, false, typeProvider.dynamicType);
@@ -3155,13 +3339,17 @@
     PropertyAccessorElementImpl setterM2g = ElementFactory.getterElement(
         setterName, false, typeProvider.dynamicType);
     classM2.accessors = <PropertyAccessorElement>[setterM2g];
-    ClassElementImpl classC = ElementFactory.classElement('C', classB.type);
-    classC.mixins = <InterfaceType>[classM1.type, classM2.type];
+    ClassElementImpl classC =
+        ElementFactory.classElement('C', interfaceType(classB));
+    classC.mixins = <InterfaceType>[
+      interfaceType(classM1),
+      interfaceType(classM2)
+    ];
     LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+        ElementFactory.library(_analysisContext, "lib");
     CompilationUnitElementImpl unit = library.definingCompilationUnit;
     unit.types = <ClassElement>[classB, classM1, classM2, classC];
-    expect(classC.type.lookUpGetter(setterName, library), setterM2g);
+    expect(interfaceType(classC).lookUpGetter(setterName, library), setterM2g);
   }
 
   void test_lookUpSetter_recursive() {
@@ -3169,12 +3357,12 @@
     // class A extends B {}
     // class B extends A {}
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
-    ClassElementImpl classB = ElementFactory.classElement("B", typeA);
-    classA.supertype = classB.type;
+    var classA = class_(name: 'A');
+    InterfaceType typeA = interfaceType(classA);
+    var classB = ElementFactory.classElement("B", typeA);
+    classA.supertype = interfaceType(classB);
     LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+        ElementFactory.library(_analysisContext, "lib");
     CompilationUnitElement unit = library.definingCompilationUnit;
     (unit as CompilationUnitElementImpl).types = <ClassElement>[classA, classB];
     expect(typeA.lookUpSetter("s", library), isNull);
@@ -3184,52 +3372,37 @@
     //
     // class A {}
     //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    InterfaceType typeA = classA.type;
+    var classA = class_(name: 'A');
+    InterfaceType typeA = interfaceType(classA);
     LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+        ElementFactory.library(_analysisContext, "lib");
     CompilationUnitElement unit = library.definingCompilationUnit;
     (unit as CompilationUnitElementImpl).types = <ClassElement>[classA];
     expect(typeA.lookUpSetter("s", library), isNull);
   }
 
   void test_resolveToBound() {
-    InterfaceTypeImpl type =
-        ElementFactory.classElement2("A").type as InterfaceTypeImpl;
+    InterfaceTypeImpl type = interfaceType(ElementFactory.classElement2('A'));
 
     // Returns this.
     expect(type.resolveToBound(null), same(type));
   }
 
   void test_setTypeArguments() {
-    InterfaceTypeImpl type =
-        ElementFactory.classElement2("A").type as InterfaceTypeImpl;
+    InterfaceTypeImpl type = interfaceType(ElementFactory.classElement2('A'));
     List<DartType> typeArguments = <DartType>[
-      ElementFactory.classElement2("B").type,
-      ElementFactory.classElement2("C").type
+      interfaceType(class_(name: 'B')),
+      interfaceType(class_(name: 'C'))
     ];
     type.typeArguments = typeArguments;
     expect(type.typeArguments, typeArguments);
   }
 
-  void test_substitute_equal() {
-    ClassElement classAE = ElementFactory.classElement2("A", ["E"]);
-    InterfaceType typeAE = classAE.type;
-    InterfaceType argumentType = ElementFactory.classElement2("B").type;
-    List<DartType> args = [argumentType];
-    List<DartType> params = [classAE.typeParameters[0].type];
-    InterfaceType typeAESubbed = typeAE.substitute2(args, params);
-    expect(typeAESubbed.element, classAE);
-    List<DartType> resultArguments = typeAESubbed.typeArguments;
-    expect(resultArguments, hasLength(1));
-    expect(resultArguments[0], argumentType);
-  }
-
   void test_substitute_exception() {
     try {
-      ClassElementImpl classA = ElementFactory.classElement2("A");
+      var classA = class_(name: 'A');
       InterfaceTypeImpl type = new InterfaceTypeImpl(classA);
-      InterfaceType argumentType = ElementFactory.classElement2("B").type;
+      InterfaceType argumentType = interfaceType(class_(name: 'B'));
       type.substitute2(<DartType>[argumentType], <DartType>[]);
       fail(
           "Expected to encounter exception, argument and parameter type array lengths not equal.");
@@ -3241,14 +3414,14 @@
   void test_substitute_notEqual() {
     // The [test_substitute_equals] above has a slightly higher level
     // implementation.
-    ClassElementImpl classA = ElementFactory.classElement2("A");
+    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];
-    InterfaceType argumentType = ElementFactory.classElement2("B").type;
+    InterfaceType argumentType = interfaceType(class_(name: 'B'));
     TypeParameterTypeImpl parameterType = new TypeParameterTypeImpl(
         new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("F")));
     InterfaceType result =
@@ -3420,7 +3593,7 @@
 }
 
 @reflectiveTest
-class TypeParameterTypeImplTest extends EngineTestCase {
+class TypeParameterTypeImplTest extends AbstractTypeTest {
   void test_creation() {
     expect(
         new TypeParameterTypeImpl(new TypeParameterElementImpl.forNode(
@@ -3448,11 +3621,11 @@
         new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
     TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
     // E << Object
-    expect(type.isMoreSpecificThan(ElementFactory.object.type), isTrue);
+    expect(type.isMoreSpecificThan(typeProvider.objectType), isTrue);
   }
 
   void test_isMoreSpecificThan_typeArguments_recursive() {
-    ClassElementImpl classS = ElementFactory.classElement2("A");
+    ClassElementImpl classS = class_(name: 'A');
     TypeParameterElementImpl typeParameterU =
         new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("U"));
     TypeParameterTypeImpl typeParameterTypeU =
@@ -3465,7 +3638,8 @@
     typeParameterU.bound = typeParameterTypeU;
     // <T extends U> and <U extends T>
     // T << S
-    expect(typeParameterTypeT.isMoreSpecificThan(classS.type), isFalse);
+    expect(
+        typeParameterTypeT.isMoreSpecificThan(interfaceType(classS)), isFalse);
   }
 
   void test_isMoreSpecificThan_typeArguments_self() {
@@ -3480,10 +3654,19 @@
     //  class A {}
     //  class B extends A {}
     //
-    ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classB = ElementFactory.classElement("B", classA.type);
-    InterfaceType typeA = classA.type;
-    InterfaceType typeB = classB.type;
+    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;
@@ -3495,10 +3678,10 @@
   }
 
   void test_isMoreSpecificThan_typeArguments_transitivity_typeParameters() {
-    ClassElementImpl classS = ElementFactory.classElement2("A");
+    ClassElementImpl classS = class_(name: 'A');
     TypeParameterElementImpl typeParameterU =
         new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("U"));
-    typeParameterU.bound = classS.type;
+    typeParameterU.bound = interfaceType(classS);
     TypeParameterTypeImpl typeParameterTypeU =
         new TypeParameterTypeImpl(typeParameterU);
     TypeParameterElementImpl typeParameterT =
@@ -3508,123 +3691,125 @@
         new TypeParameterTypeImpl(typeParameterT);
     // <T extends U> and <U extends S>
     // T << S
-    expect(typeParameterTypeT.isMoreSpecificThan(classS.type), isTrue);
+    expect(
+        typeParameterTypeT.isMoreSpecificThan(interfaceType(classS)), isTrue);
   }
 
   void test_isMoreSpecificThan_typeArguments_upperBound() {
-    ClassElementImpl classS = ElementFactory.classElement2("A");
+    ClassElementImpl classS = class_(name: 'A');
     TypeParameterElementImpl typeParameterT =
         new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("T"));
-    typeParameterT.bound = classS.type;
+    typeParameterT.bound = interfaceType(classS);
     TypeParameterTypeImpl typeParameterTypeT =
         new TypeParameterTypeImpl(typeParameterT);
     // <T extends S>
     // T << S
-    expect(typeParameterTypeT.isMoreSpecificThan(classS.type), isTrue);
+    expect(
+        typeParameterTypeT.isMoreSpecificThan(interfaceType(classS)), isTrue);
   }
 
   void test_resolveToBound_bound() {
-    ClassElementImpl classS = ElementFactory.classElement2("A");
+    ClassElementImpl classS = class_(name: 'A');
     TypeParameterElementImpl element =
         new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
-    element.bound = classS.type;
+    element.bound = interfaceType(classS);
     TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
-    expect(type.resolveToBound(null), same(classS.type));
+    expect(type.resolveToBound(null), interfaceType(classS));
   }
 
   void test_resolveToBound_bound_nullableInner() {
-    ClassElementImpl classS = ElementFactory.classElement2("A");
+    ClassElementImpl classS = class_(name: 'A');
     TypeParameterElementImpl element =
         new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
-    element.bound =
-        (classS.type as TypeImpl).withNullability(NullabilitySuffix.question);
+    element.bound = (interfaceType(classS) as TypeImpl)
+        .withNullability(NullabilitySuffix.question);
     TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
     expect(type.resolveToBound(null), same(element.bound));
   }
 
   void test_resolveToBound_bound_nullableInnerOuter() {
-    ClassElementImpl classS = ElementFactory.classElement2("A");
+    ClassElementImpl classS = class_(name: 'A');
     TypeParameterElementImpl element =
         new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
-    element.bound =
-        (classS.type as TypeImpl).withNullability(NullabilitySuffix.question);
+    element.bound = (interfaceType(classS) as TypeImpl)
+        .withNullability(NullabilitySuffix.question);
     TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
         .withNullability(NullabilitySuffix.question);
     expect(type.resolveToBound(null), same(element.bound));
   }
 
   void test_resolveToBound_bound_nullableInnerStarOuter() {
-    ClassElementImpl classS = ElementFactory.classElement2("A");
+    ClassElementImpl classS = class_(name: 'A');
     TypeParameterElementImpl element =
         new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
-    element.bound =
-        (classS.type as TypeImpl).withNullability(NullabilitySuffix.star);
+    element.bound = (interfaceType(classS) as TypeImpl)
+        .withNullability(NullabilitySuffix.star);
     TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
         .withNullability(NullabilitySuffix.question);
     expect(
         type.resolveToBound(null),
-        equals((classS.type as TypeImpl)
+        equals((interfaceType(classS) as TypeImpl)
             .withNullability(NullabilitySuffix.question)));
   }
 
   void test_resolveToBound_bound_nullableOuter() {
-    ClassElementImpl classS = ElementFactory.classElement2("A");
+    ClassElementImpl classS = class_(name: 'A');
     TypeParameterElementImpl element =
         new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
-    element.bound = classS.type;
+    element.bound = interfaceType(classS);
     TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
         .withNullability(NullabilitySuffix.question);
     expect(
         type.resolveToBound(null),
-        equals((classS.type as TypeImpl)
+        equals((interfaceType(classS) as TypeImpl)
             .withNullability(NullabilitySuffix.question)));
   }
 
   void test_resolveToBound_bound_starInner() {
-    ClassElementImpl classS = ElementFactory.classElement2("A");
+    ClassElementImpl classS = class_(name: 'A');
     TypeParameterElementImpl element =
         new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
-    element.bound =
-        (classS.type as TypeImpl).withNullability(NullabilitySuffix.star);
+    element.bound = (interfaceType(classS) as TypeImpl)
+        .withNullability(NullabilitySuffix.star);
     TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
     expect(type.resolveToBound(null), same(element.bound));
   }
 
   void test_resolveToBound_bound_starInnerNullableOuter() {
-    ClassElementImpl classS = ElementFactory.classElement2("A");
+    ClassElementImpl classS = class_(name: 'A');
     TypeParameterElementImpl element =
         new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
-    element.bound =
-        (classS.type as TypeImpl).withNullability(NullabilitySuffix.question);
+    element.bound = (interfaceType(classS) as TypeImpl)
+        .withNullability(NullabilitySuffix.question);
     TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
         .withNullability(NullabilitySuffix.star);
     expect(type.resolveToBound(null), same(element.bound));
   }
 
   void test_resolveToBound_bound_starOuter() {
-    ClassElementImpl classS = ElementFactory.classElement2("A");
+    ClassElementImpl classS = class_(name: 'A');
     TypeParameterElementImpl element =
         new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
-    element.bound = classS.type;
+    element.bound = interfaceType(classS);
     TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
         .withNullability(NullabilitySuffix.star);
     expect(
         type.resolveToBound(null),
-        same(
-            (classS.type as TypeImpl).withNullability(NullabilitySuffix.star)));
+        (interfaceType(classS) as TypeImpl)
+            .withNullability(NullabilitySuffix.star));
   }
 
   void test_resolveToBound_nestedBound() {
-    ClassElementImpl classS = ElementFactory.classElement2("A");
+    ClassElementImpl classS = class_(name: 'A');
     TypeParameterElementImpl elementE =
         new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
-    elementE.bound = classS.type;
+    elementE.bound = interfaceType(classS);
     TypeParameterTypeImpl typeE = new TypeParameterTypeImpl(elementE);
     TypeParameterElementImpl elementF =
         new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("F"));
     elementF.bound = typeE;
     TypeParameterTypeImpl typeF = new TypeParameterTypeImpl(elementE);
-    expect(typeF.resolveToBound(null), same(classS.type));
+    expect(typeF.resolveToBound(null), interfaceType(classS));
   }
 
   void test_resolveToBound_unbound() {
@@ -3659,16 +3844,24 @@
 }
 
 @reflectiveTest
-class VoidTypeImplTest extends EngineTestCase {
+class VoidTypeImplTest extends AbstractTypeTest {
   /**
    * Reference {code VoidTypeImpl.getInstance()}.
    */
   DartType _voidType = VoidTypeImpl.instance;
 
   void test_isMoreSpecificThan_void_A() {
-    ClassElement classA = ElementFactory.classElement2("A");
-    // ignore: deprecated_member_use_from_same_package
-    expect(_voidType.isMoreSpecificThan(classA.type), isFalse);
+    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() {
@@ -3682,8 +3875,16 @@
   }
 
   void test_isSubtypeOf_void_A() {
-    ClassElement classA = ElementFactory.classElement2("A");
-    expect(_voidType.isSubtypeOf(classA.type), isFalse);
+    ClassElement classA = class_(name: 'A');
+    expect(
+      _voidType.isSubtypeOf(
+        classA.instantiate(
+          typeArguments: [],
+          nullabilitySuffix: NullabilitySuffix.star,
+        ),
+      ),
+      isFalse,
+    );
   }
 
   void test_isSubtypeOf_void_dynamic() {
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 eb473da..6b6aa60 100644
--- a/pkg/analyzer/test/src/dart/element/function_type_test.dart
+++ b/pkg/analyzer/test/src/dart/element/function_type_test.dart
@@ -3,14 +3,18 @@
 // 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/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/testing/test_type_provider.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../../generated/elements_types_mixin.dart';
+
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(FunctionTypeTest);
@@ -30,19 +34,21 @@
 }
 
 @reflectiveTest
-class FunctionTypeTest {
+class FunctionTypeTest with ElementsTypesMixin {
   static const bug_33294_fixed = false;
   static const bug_33300_fixed = false;
   static const bug_33301_fixed = false;
   static const bug_33302_fixed = false;
 
-  final objectType = new InterfaceTypeImpl(new MockClassElement('Object'));
+  final TypeProvider typeProvider = TestTypeProvider();
 
-  final mapType = _makeMapType();
+  InterfaceType get intType => typeProvider.intType;
 
-  final listType = _makeListType();
+  ClassElement get listElement => typeProvider.listElement;
 
-  final intType = new InterfaceTypeImpl(new MockClassElement('int'));
+  ClassElement get mapElement => typeProvider.mapElement;
+
+  InterfaceType get objectType => typeProvider.objectType;
 
   void basicChecks(FunctionType f,
       {element,
@@ -81,19 +87,44 @@
     expect(f.typeFormals, typeFormals, reason: 'typeFormals');
   }
 
-  DartType listOf(DartType elementType) => listType.instantiate([elementType]);
+  GenericTypeAliasElementImpl genericTypeAliasElement(
+    String name, {
+    List<ParameterElement> parameters: const [],
+    DartType returnType,
+    List<TypeParameterElement> typeParameters: const [],
+    List<TypeParameterElement> innerTypeParameters: const [],
+  }) {
+    var aliasElement = GenericTypeAliasElementImpl(name, 0);
+    aliasElement.typeParameters = typeParameters;
+
+    var functionElement = GenericFunctionTypeElementImpl.forOffset(0);
+    aliasElement.function = functionElement;
+    functionElement.typeParameters = innerTypeParameters;
+    functionElement.parameters = parameters;
+    functionElement.returnType = returnType;
+
+    return aliasElement;
+  }
+
+  DartType listOf(DartType elementType) => listElement.instantiate(
+        typeArguments: [elementType],
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
 
   DartType mapOf(DartType keyType, DartType valueType) =>
-      mapType.instantiate([keyType, valueType]);
+      mapElement.instantiate(
+        typeArguments: [keyType, valueType],
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
 
   test_forInstantiatedTypedef_bothTypeParameters_noTypeArgs() {
     // typedef F<T> = Map<T, U> Function<U>();
-    var t = new MockTypeParameterElement('T');
-    var u = new MockTypeParameterElement('U');
-    var e = new MockGenericTypeAliasElement('F',
+    var t = typeParameter('T');
+    var u = typeParameter('U');
+    var e = genericTypeAliasElement('F',
         typeParameters: [t],
         innerTypeParameters: [u],
-        returnType: mapOf(t.type, u.type));
+        returnType: mapOf(typeParameterType(t), typeParameterType(u)));
     FunctionType f = new FunctionTypeImpl.forTypedef(e);
     // Note: forTypedef returns the type `<T>() -> Map<T, U>`.
     // See https://github.com/dart-lang/sdk/issues/34657.
@@ -102,14 +133,14 @@
         displayName: 'F',
         name: 'F',
         typeFormals: [same(t)],
-        returnType: mapOf(t.type, u.type));
+        returnType: mapOf(typeParameterType(t), typeParameterType(u)));
   }
 
   test_forInstantiatedTypedef_innerTypeParameter_noTypeArgs() {
     // typedef F = T F<T>();
-    var t = new MockTypeParameterElement('T');
-    var e = new MockGenericTypeAliasElement('F',
-        innerTypeParameters: [t], returnType: t.type);
+    var t = typeParameter('T');
+    var e = genericTypeAliasElement('F',
+        innerTypeParameters: [t], returnType: typeParameterType(t));
     FunctionType f = new FunctionTypeImpl.forTypedef(e);
     // Note: forTypedef returns the type `() -> T`.
     // See https://github.com/dart-lang/sdk/issues/34657.
@@ -117,12 +148,12 @@
         element: same(e),
         displayName: 'F',
         name: 'F',
-        returnType: same(t.type));
+        returnType: typeParameterType(t));
   }
 
   test_forInstantiatedTypedef_noTypeParameters_noTypeArgs() {
     // typedef F = void Function();
-    var e = new MockGenericTypeAliasElement('F');
+    var e = genericTypeAliasElement('F');
     FunctionType f = new FunctionTypeImpl.forTypedef(e);
     // Note: forTypedef returns the type `() -> void`.
     basicChecks(f, element: same(e), displayName: 'F', name: 'F');
@@ -130,9 +161,9 @@
 
   test_forInstantiatedTypedef_outerTypeParameters_noTypeArgs() {
     // typedef F<T> = T Function();
-    var t = new MockTypeParameterElement('T');
-    var e = new MockGenericTypeAliasElement('F',
-        typeParameters: [t], returnType: t.type);
+    var t = typeParameter('T');
+    var e = genericTypeAliasElement('F',
+        typeParameters: [t], returnType: typeParameterType(t));
     FunctionType f = new FunctionTypeImpl.forTypedef(e);
     // Note: forTypedef returns the type `<T>() -> T`.
     // See https://github.com/dart-lang/sdk/issues/34657.
@@ -141,64 +172,65 @@
         displayName: 'F',
         name: 'F',
         typeFormals: [same(t)],
-        returnType: same(t.type));
+        returnType: typeParameterType(t));
   }
 
   test_forTypedef() {
-    var e = new MockGenericTypeAliasElement('F');
-    basicChecks(e.type, element: same(e), displayName: 'F', name: 'F');
+    var e = genericTypeAliasElement('F');
+    basicChecks(functionTypeAliasType(e),
+        element: same(e), displayName: 'F', name: 'F');
     basicChecks(e.function.type,
         element: same(e.function), displayName: 'dynamic Function()');
   }
 
   test_forTypedef_innerAndOuterTypeParameter() {
     // typedef F<T> = T Function<U>(U p);
-    var t = new MockTypeParameterElement('T');
-    var u = new MockTypeParameterElement('U');
-    var p = new MockParameterElement('p', type: u.type);
-    var e = new MockGenericTypeAliasElement('F',
+    var t = typeParameter('T');
+    var u = typeParameter('U');
+    var p = requiredParameter('p', type: typeParameterType(u));
+    var e = genericTypeAliasElement('F',
         typeParameters: [t],
         innerTypeParameters: [u],
-        returnType: t.type,
+        returnType: typeParameterType(t),
         parameters: [p]);
     basicChecks(e.type,
         element: same(e),
         displayName: 'F',
         name: 'F',
-        returnType: same(t.type),
-        normalParameterTypes: [same(u.type)],
+        returnType: typeParameterType(t),
+        normalParameterTypes: [typeParameterType(u)],
         normalParameterNames: ['p'],
         parameters: [same(p)],
         typeFormals: [same(t)]);
     basicChecks(e.function.type,
         element: same(e.function),
         displayName: 'T Function<U>(U)',
-        returnType: same(t.type),
-        typeArguments: [same(t.type)],
+        returnType: typeParameterType(t),
+        typeArguments: [typeParameterType(t)],
         typeParameters: [same(t)],
         typeFormals: [same(u)],
-        normalParameterTypes: [same(u.type)],
+        normalParameterTypes: [typeParameterType(u)],
         normalParameterNames: ['p'],
         parameters: [same(p)]);
   }
 
   test_forTypedef_innerAndOuterTypeParameter_instantiate() {
     // typedef F<T> = T Function<U>(U p);
-    var t = new MockTypeParameterElement('T');
-    var u = new MockTypeParameterElement('U');
-    var p = new MockParameterElement('p', type: u.type);
-    var e = new MockGenericTypeAliasElement('F',
+    var t = typeParameter('T');
+    var u = typeParameter('U');
+    var p = requiredParameter('p', type: typeParameterType(u));
+    var e = genericTypeAliasElement('F',
         typeParameters: [t],
         innerTypeParameters: [u],
-        returnType: t.type,
+        returnType: typeParameterType(t),
         parameters: [p]);
-    var instantiated = e.type.instantiate([objectType]);
+    var instantiated = functionTypeAliasType(e, typeArguments: [objectType]);
     basicChecks(instantiated,
         element: same(e),
         displayName: 'F<Object>',
         name: 'F',
         returnType: same(objectType),
-        normalParameterTypes: [same(u.type)],
+        normalParameterTypes: [typeParameterType(u)],
         normalParameterNames: ['p'],
         parameters: [same(p)],
         typeFormals: isNotNull,
@@ -213,25 +245,25 @@
 
   test_forTypedef_innerTypeParameter() {
     // typedef F = T Function<T>();
-    var t = new MockTypeParameterElement('T');
-    var e = new MockGenericTypeAliasElement('F',
-        innerTypeParameters: [t], returnType: t.type);
-    basicChecks(e.type,
+    var t = typeParameter('T');
+    var e = genericTypeAliasElement('F',
+        innerTypeParameters: [t], returnType: typeParameterType(t));
+    basicChecks(functionTypeAliasType(e),
         element: same(e),
         displayName: 'F',
         name: 'F',
-        returnType: same(t.type));
+        returnType: typeParameterType(t));
     basicChecks(e.function.type,
         element: same(e.function),
         displayName: 'T Function<T>()',
-        returnType: same(t.type),
+        returnType: typeParameterType(t),
         typeFormals: [same(t)]);
   }
 
   test_forTypedef_normalParameter() {
-    var p = new MockParameterElement('p');
-    var e = new MockGenericTypeAliasElement('F', parameters: [p]);
-    basicChecks(e.type,
+    var p = requiredParameter('p', type: dynamicType);
+    var e = genericTypeAliasElement('F', parameters: [p]);
+    basicChecks(functionTypeAliasType(e),
         element: same(e),
         displayName: 'F',
         name: 'F',
@@ -249,14 +281,14 @@
   test_forTypedef_recursive_via_interfaceTypes() {
     // typedef F = List<G> Function();
     // typedef G = List<F> Function();
-    var f = new MockGenericTypeAliasElement('F');
-    var g = new MockGenericTypeAliasElement('G');
-    f.returnType = listOf(g.function.type);
-    g.returnType = listOf(f.function.type);
-    basicChecks(f.type,
+    var f = genericTypeAliasElement('F');
+    var g = genericTypeAliasElement('G');
+    f.function.returnType = listOf(g.function.type);
+    g.function.returnType = listOf(f.function.type);
+    basicChecks(functionTypeAliasType(f),
         element: same(f), displayName: 'F', name: 'F', returnType: isNotNull);
-    var fReturn = f.type.returnType;
-    expect(fReturn.element, same(listType.element));
+    var fReturn = functionTypeAliasType(f).returnType;
+    expect(fReturn.element, same(listElement));
     if (bug_33302_fixed) {
       expect(fReturn.displayName, 'List<G>');
     } else {
@@ -265,7 +297,7 @@
     var fReturnArg = (fReturn as InterfaceType).typeArguments[0];
     expect(fReturnArg.element, same(g.function));
     var fReturnArgReturn = (fReturnArg as FunctionType).returnType;
-    expect(fReturnArgReturn.element, same(listType.element));
+    expect(fReturnArgReturn.element, same(listElement));
     expect((fReturnArgReturn as InterfaceType).typeArguments[0],
         new TypeMatcher<CircularFunctionTypeImpl>());
     basicChecks(f.function.type,
@@ -276,10 +308,10 @@
       expect(
           f.function.type.displayName, 'List<List<...> Function()> Function()');
     }
-    basicChecks(g.type,
+    basicChecks(functionTypeAliasType(g),
         element: same(g), displayName: 'G', name: 'G', returnType: isNotNull);
-    var gReturn = g.type.returnType;
-    expect(gReturn.element, same(listType.element));
+    var gReturn = functionTypeAliasType(g).returnType;
+    expect(gReturn.element, same(listElement));
     if (bug_33302_fixed) {
       expect(gReturn.displayName, 'List<F>');
     } else {
@@ -288,7 +320,7 @@
     var gReturnArg = (gReturn as InterfaceType).typeArguments[0];
     expect(gReturnArg.element, same(f.function));
     var gReturnArgReturn = (gReturnArg as FunctionType).returnType;
-    expect(gReturnArgReturn.element, same(listType.element));
+    expect(gReturnArgReturn.element, same(listElement));
     expect((gReturnArgReturn as InterfaceType).typeArguments[0],
         new TypeMatcher<CircularFunctionTypeImpl>());
     basicChecks(g.function.type,
@@ -304,11 +336,11 @@
   test_forTypedef_recursive_via_parameterTypes() {
     // typedef F = void Function(G g);
     // typedef G = void Function(F f);
-    var f = new MockGenericTypeAliasElement('F', returnType: voidType);
-    var g = new MockGenericTypeAliasElement('G', returnType: voidType);
-    f.parameters = [new MockParameterElement('g', type: g.function.type)];
-    g.parameters = [new MockParameterElement('f', type: f.function.type)];
-    basicChecks(f.type,
+    var f = genericTypeAliasElement('F', returnType: voidType);
+    var g = genericTypeAliasElement('G', returnType: voidType);
+    f.function.parameters = [requiredParameter('g', type: g.function.type)];
+    g.function.parameters = [requiredParameter('f', type: f.function.type)];
+    basicChecks(functionTypeAliasType(f),
         element: same(f),
         displayName: 'F',
         name: 'F',
@@ -316,7 +348,7 @@
         normalParameterTypes: hasLength(1),
         normalParameterNames: ['g'],
         returnType: same(voidType));
-    var fParamType = f.type.normalParameterTypes[0];
+    var fParamType = functionTypeAliasType(f).normalParameterTypes[0];
     expect(fParamType.element, same(g.function));
     expect((fParamType as FunctionType).normalParameterTypes[0],
         new TypeMatcher<CircularFunctionTypeImpl>());
@@ -332,7 +364,7 @@
     } else {
       expect(f.function.type.displayName, 'void Function(void Function(...))');
     }
-    basicChecks(g.type,
+    basicChecks(functionTypeAliasType(g),
         element: same(g),
         displayName: 'G',
         name: 'G',
@@ -340,7 +372,7 @@
         normalParameterTypes: hasLength(1),
         normalParameterNames: ['f'],
         returnType: same(voidType));
-    var gParamType = g.type.normalParameterTypes[0];
+    var gParamType = functionTypeAliasType(g).normalParameterTypes[0];
     expect(gParamType.element, same(f.function));
     expect((gParamType as FunctionType).normalParameterTypes[0],
         new TypeMatcher<CircularFunctionTypeImpl>());
@@ -361,13 +393,13 @@
   test_forTypedef_recursive_via_returnTypes() {
     // typedef F = G Function();
     // typedef G = F Function();
-    var f = new MockGenericTypeAliasElement('F');
-    var g = new MockGenericTypeAliasElement('G');
-    f.returnType = g.function.type;
-    g.returnType = f.function.type;
-    basicChecks(f.type,
+    var f = genericTypeAliasElement('F');
+    var g = genericTypeAliasElement('G');
+    f.function.returnType = g.function.type;
+    g.function.returnType = f.function.type;
+    basicChecks(functionTypeAliasType(f),
         element: same(f), displayName: 'F', name: 'F', returnType: isNotNull);
-    var fReturn = f.type.returnType;
+    var fReturn = functionTypeAliasType(f).returnType;
     expect(fReturn.element, same(g.function));
     expect((fReturn as FunctionType).returnType,
         new TypeMatcher<CircularFunctionTypeImpl>());
@@ -378,9 +410,9 @@
     } else {
       expect(f.function.type.displayName, '... Function() Function()');
     }
-    basicChecks(g.type,
+    basicChecks(functionTypeAliasType(g),
         element: same(g), displayName: 'G', name: 'G', returnType: isNotNull);
-    var gReturn = g.type.returnType;
+    var gReturn = functionTypeAliasType(g).returnType;
     expect(gReturn.element, same(f.function));
     expect((gReturn as FunctionType).returnType,
         new TypeMatcher<CircularFunctionTypeImpl>());
@@ -394,8 +426,8 @@
   }
 
   test_forTypedef_returnType() {
-    var e = new MockGenericTypeAliasElement('F', returnType: objectType);
-    basicChecks(e.type,
+    var e = genericTypeAliasElement('F', returnType: objectType);
+    basicChecks(functionTypeAliasType(e),
         element: same(e), displayName: 'F', name: 'F', returnType: objectType);
     basicChecks(e.function.type,
         element: same(e.function),
@@ -404,28 +436,29 @@
   }
 
   test_forTypedef_returnType_null() {
-    var e = new MockGenericTypeAliasElement.withNullReturn('F');
-    basicChecks(e.type, element: same(e), displayName: 'F', name: 'F');
+    var e = genericTypeAliasElement('F');
+    basicChecks(functionTypeAliasType(e),
+        element: same(e), displayName: 'F', name: 'F');
     basicChecks(e.function.type,
         element: same(e.function), displayName: 'dynamic Function()');
   }
 
   test_forTypedef_typeParameter() {
     // typedef F<T> = T Function();
-    var t = new MockTypeParameterElement('T');
-    var e = new MockGenericTypeAliasElement('F',
-        typeParameters: [t], returnType: t.type);
+    var t = typeParameter('T');
+    var e = genericTypeAliasElement('F',
+        typeParameters: [t], returnType: typeParameterType(t));
     basicChecks(e.type,
         element: same(e),
         displayName: 'F',
         name: 'F',
-        returnType: same(t.type),
+        returnType: typeParameterType(t),
         typeFormals: [same(t)]);
     basicChecks(e.function.type,
         element: same(e.function),
         displayName: 'T Function()',
-        returnType: same(t.type),
-        typeArguments: [same(t.type)],
+        returnType: typeParameterType(t),
+        typeArguments: [typeParameterType(t)],
         typeParameters: [same(t)]);
   }
 
@@ -436,9 +469,10 @@
 
   test_synthetic_instantiate() {
     // T Function<T>(T x)
-    var t = new MockTypeParameterElement('T');
-    var x = new MockParameterElement('x', type: t.type);
-    FunctionType f = new FunctionTypeImpl.synthetic(t.type, [t], [x]);
+    var t = typeParameter('T');
+    var x = requiredParameter('x', type: typeParameterType(t));
+    FunctionType f =
+        new FunctionTypeImpl.synthetic(typeParameterType(t), [t], [x]);
     FunctionType instantiated = f.instantiate([objectType]);
     basicChecks(instantiated,
         element: isNull,
@@ -451,7 +485,7 @@
 
   test_synthetic_instantiate_argument_length_mismatch() {
     // dynamic Function<T>()
-    var t = new MockTypeParameterElement('T');
+    var t = typeParameter('T');
     FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [t], []);
     expect(() => f.instantiate([]), throwsA(new TypeMatcher<ArgumentError>()));
   }
@@ -463,9 +497,10 @@
 
   test_synthetic_instantiate_share_parameters() {
     // T Function<T>(int x)
-    var t = new MockTypeParameterElement('T');
-    var x = new MockParameterElement('x', type: intType);
-    FunctionType f = new FunctionTypeImpl.synthetic(t.type, [t], [x]);
+    var t = typeParameter('T');
+    var x = requiredParameter('x', type: intType);
+    FunctionType f =
+        new FunctionTypeImpl.synthetic(typeParameterType(t), [t], [x]);
     FunctionType instantiated = f.instantiate([objectType]);
     basicChecks(instantiated,
         element: isNull,
@@ -477,8 +512,7 @@
   }
 
   test_synthetic_namedParameter() {
-    var p = new MockParameterElement('x',
-        type: objectType, parameterKind: ParameterKind.NAMED);
+    var p = namedParameter('x', type: objectType);
     FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p]);
     basicChecks(f,
         element: isNull,
@@ -491,7 +525,7 @@
   }
 
   test_synthetic_normalParameter() {
-    var p = new MockParameterElement('x', type: objectType);
+    var p = requiredParameter('x', type: objectType);
     FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p]);
     basicChecks(f,
         element: isNull,
@@ -505,8 +539,7 @@
   }
 
   test_synthetic_optionalParameter() {
-    var p = new MockParameterElement('x',
-        type: objectType, parameterKind: ParameterKind.POSITIONAL);
+    var p = positionalParameter('x', type: objectType);
     FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p]);
     basicChecks(f,
         element: isNull,
@@ -529,39 +562,44 @@
 
   test_synthetic_substitute() {
     // Map<T, U> Function<U extends T>(T x, U y)
-    var t = new MockTypeParameterElement('T');
-    var u = new MockTypeParameterElement('U', bound: t.type);
-    var x = new MockParameterElement('x', type: t.type);
-    var y = new MockParameterElement('y', type: u.type);
-    FunctionType f =
-        new FunctionTypeImpl.synthetic(mapOf(t.type, u.type), [u], [x, y]);
-    FunctionType substituted = f.substitute2([objectType], [t.type]);
+    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));
+    FunctionType f = new FunctionTypeImpl.synthetic(
+        mapOf(typeParameterType(t), typeParameterType(u)), [u], [x, y]);
+    FunctionType substituted =
+        f.substitute2([objectType], [typeParameterType(t)]);
     var uSubstituted = substituted.typeFormals[0];
     basicChecks(substituted,
         element: isNull,
         displayName: 'Map<Object, U> Function<U extends Object>(Object, U)',
-        returnType: mapOf(objectType, uSubstituted.type),
+        returnType: mapOf(objectType, typeParameterType(uSubstituted)),
         typeFormals: [uSubstituted],
         normalParameterNames: ['x', 'y'],
-        normalParameterTypes: [same(objectType), same(uSubstituted.type)],
+        normalParameterTypes: [
+          same(objectType),
+          typeParameterType(uSubstituted)
+        ],
         parameters: hasLength(2));
   }
 
   test_synthetic_substitute_argument_length_mismatch() {
     // dynamic Function()
-    var t = new MockTypeParameterElement('T');
+    var t = typeParameter('T');
     FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], []);
-    expect(() => f.substitute2([], [t.type]),
+    expect(() => f.substitute2([], [typeParameterType(t)]),
         throwsA(new TypeMatcher<ArgumentError>()));
   }
 
   test_synthetic_substitute_share_returnType_and_parameters() {
     // int Function<U extends T>(int x)
-    var t = new MockTypeParameterElement('T');
-    var u = new MockTypeParameterElement('U', bound: t.type);
-    var x = new MockParameterElement('x', type: intType);
+    var t = typeParameter('T');
+    var u = typeParameter('U', bound: typeParameterType(t));
+    var x = requiredParameter('x', type: intType);
     FunctionType f = new FunctionTypeImpl.synthetic(intType, [u], [x]);
-    FunctionType substituted = f.substitute2([objectType], [t.type]);
+    FunctionType substituted =
+        f.substitute2([objectType], [typeParameterType(t)]);
     basicChecks(substituted,
         element: isNull,
         displayName: 'int Function<U extends Object>(int)',
@@ -576,56 +614,61 @@
 
   test_synthetic_substitute_share_returnType_and_typeFormals() {
     // int Function<U>(T x, U y)
-    var t = new MockTypeParameterElement('T');
-    var u = new MockTypeParameterElement('U');
-    var x = new MockParameterElement('x', type: t.type);
-    var y = new MockParameterElement('y', type: u.type);
+    var t = typeParameter('T');
+    var u = typeParameter('U');
+    var x = requiredParameter('x', type: typeParameterType(t));
+    var y = requiredParameter('y', type: typeParameterType(u));
     FunctionType f = new FunctionTypeImpl.synthetic(intType, [u], [x, y]);
-    FunctionType substituted = f.substitute2([objectType], [t.type]);
+    FunctionType substituted =
+        f.substitute2([objectType], [typeParameterType(t)]);
     basicChecks(substituted,
         element: isNull,
         displayName: 'int Function<U>(Object, U)',
         returnType: same(f.returnType),
         typeFormals: same(f.typeFormals),
         normalParameterNames: ['x', 'y'],
-        normalParameterTypes: [same(objectType), same(u.type)],
+        normalParameterTypes: [same(objectType), typeParameterType(u)],
         parameters: hasLength(2));
   }
 
   test_synthetic_substitute_share_typeFormals_and_parameters() {
     // T Function<U>(U x)
-    var t = new MockTypeParameterElement('T');
-    var u = new MockTypeParameterElement('U');
-    var x = new MockParameterElement('x', type: u.type);
-    FunctionType f = new FunctionTypeImpl.synthetic(t.type, [u], [x]);
-    FunctionType substituted = f.substitute2([objectType], [t.type]);
+    var t = typeParameter('T');
+    var u = typeParameter('U');
+    var x = requiredParameter('x', type: typeParameterType(u));
+    FunctionType f =
+        new FunctionTypeImpl.synthetic(typeParameterType(t), [u], [x]);
+    FunctionType substituted =
+        f.substitute2([objectType], [typeParameterType(t)]);
     basicChecks(substituted,
         element: isNull,
         displayName: 'Object Function<U>(U)',
         returnType: same(objectType),
         typeFormals: same(f.typeFormals),
         normalParameterNames: ['x'],
-        normalParameterTypes: [same(u.type)],
+        normalParameterTypes: [typeParameterType(u)],
         parameters: same(f.parameters));
   }
 
   test_synthetic_substitute_unchanged() {
     // dynamic Function<U>(U x)
-    var t = new MockTypeParameterElement('T');
-    var u = new MockTypeParameterElement('U');
-    var x = new MockParameterElement('x', type: u.type);
+    var t = typeParameter('T');
+    var u = typeParameter('U');
+    var x = requiredParameter('x', type: typeParameterType(u));
     FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [u], [x]);
-    FunctionType substituted = f.substitute2([objectType], [t.type]);
+    FunctionType substituted =
+        f.substitute2([objectType], [typeParameterType(t)]);
     expect(substituted, same(f));
   }
 
   test_synthetic_typeFormals() {
-    var t = new MockTypeParameterElement('T');
-    FunctionType f = new FunctionTypeImpl.synthetic(t.type, [t], []);
+    var t = typeParameter('T');
+    FunctionType f =
+        new FunctionTypeImpl.synthetic(typeParameterType(t), [t], []);
     basicChecks(f,
         element: isNull,
         displayName: 'T Function<T>()',
-        returnType: same(t.type),
+        returnType: typeParameterType(t),
         typeFormals: [same(t)]);
   }
 
@@ -636,29 +679,12 @@
   }
 
   test_unnamedConstructor_instantiate_argument_length_mismatch() {
-    var t = new MockTypeParameterElement('T');
+    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_noop() {
-    var t = new MockTypeParameterElement('T');
-    var p = new MockParameterElement('x', type: t.type);
-    var e = new MockFunctionTypedElement(typeParameters: [t], parameters: [p]);
-    FunctionType f = new FunctionTypeImpl(e);
-    var instantiated = f.instantiate([t.type]);
-    basicChecks(instantiated,
-        element: same(e),
-        displayName: 'dynamic Function(T)',
-        typeArguments: hasLength(1),
-        typeParameters: [same(t)],
-        normalParameterNames: ['x'],
-        normalParameterTypes: [same(t.type)],
-        parameters: [same(p)]);
-    expect(instantiated.typeArguments[0], same(t.type));
-  }
-
   test_unnamedConstructor_instantiate_noTypeParameters() {
     var e = new MockFunctionTypedElement();
     FunctionType f = new FunctionTypeImpl(e);
@@ -666,8 +692,8 @@
   }
 
   test_unnamedConstructor_instantiate_parameterType_simple() {
-    var t = new MockTypeParameterElement('T');
-    var p = new MockParameterElement('x', type: t.type);
+    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]);
@@ -685,9 +711,9 @@
   }
 
   test_unnamedConstructor_instantiate_returnType_simple() {
-    var t = new MockTypeParameterElement('T');
-    var e =
-        new MockFunctionTypedElement(typeParameters: [t], returnType: t.type);
+    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,
@@ -700,7 +726,7 @@
   }
 
   test_unnamedConstructor_namedParameter() {
-    var p = new MockParameterElement('x', parameterKind: ParameterKind.NAMED);
+    var p = namedParameter('x', type: dynamicType);
     var e = new MockFunctionTypedElement(parameters: [p]);
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
@@ -711,8 +737,7 @@
   }
 
   test_unnamedConstructor_namedParameter_object() {
-    var p = new MockParameterElement('x',
-        parameterKind: ParameterKind.NAMED, type: objectType);
+    var p = namedParameter('x', type: objectType);
     var e = new MockFunctionTypedElement(parameters: [p]);
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
@@ -729,20 +754,20 @@
   }
 
   test_unnamedConstructor_nonTypedef_withTypeArguments() {
-    var t = new MockTypeParameterElement('T');
-    var c = new MockClassElement('C', typeParameters: [t]);
-    var e = new MockMethodElement(c, returnType: t.type);
+    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: [same(t.type)],
+        typeArguments: [typeParameterType(t)],
         typeParameters: [same(t)],
         displayName: 'T Function()',
-        returnType: same(t.type));
+        returnType: typeParameterType(t));
   }
 
   test_unnamedConstructor_normalParameter() {
-    var p = new MockParameterElement('x');
+    var p = requiredParameter('x', type: dynamicType);
     var e = new MockFunctionTypedElement(parameters: [p]);
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
@@ -754,7 +779,7 @@
   }
 
   test_unnamedConstructor_normalParameter_object() {
-    var p = new MockParameterElement('x', type: objectType);
+    var p = requiredParameter('x', type: objectType);
     var e = new MockFunctionTypedElement(parameters: [p]);
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
@@ -766,8 +791,7 @@
   }
 
   test_unnamedConstructor_optionalParameter() {
-    var p =
-        new MockParameterElement('x', parameterKind: ParameterKind.POSITIONAL);
+    var p = positionalParameter('x', type: dynamicType);
     var e = new MockFunctionTypedElement(parameters: [p]);
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
@@ -779,8 +803,7 @@
   }
 
   test_unnamedConstructor_optionalParameter_object() {
-    var p = new MockParameterElement('x',
-        parameterKind: ParameterKind.POSITIONAL, type: objectType);
+    var p = positionalParameter('x', type: objectType);
     var e = new MockFunctionTypedElement(parameters: [p]);
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
@@ -810,9 +833,9 @@
   }
 
   test_unnamedConstructor_staticMethod_ignores_enclosing_type_params() {
-    var t = new MockTypeParameterElement('T');
-    var c = new MockClassElement('C', typeParameters: [t]);
-    var e = new MockMethodElement(c, isStatic: true);
+    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));
   }
@@ -821,11 +844,11 @@
     // abstract class C<T> {
     //   dynamic f();
     // }
-    var t = new MockTypeParameterElement('T');
-    var c = new MockClassElement('C', typeParameters: [t]);
+    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([], [t.type]),
+    expect(() => f.substitute2([], [typeParameterType(t)]),
         throwsA(new TypeMatcher<ArgumentError>()));
   }
 
@@ -833,20 +856,20 @@
     // abstract class C<T> {
     //   Map<S, V> f<S extends T, T extends U, V extends T>();
     // }
-    var s = new MockTypeParameterElement('S');
-    var t = new MockTypeParameterElement('T');
-    var u = new MockTypeParameterElement('U');
-    var v = new MockTypeParameterElement('V');
-    s.bound = t.type;
-    t.bound = u.type;
-    v.bound = t.type;
-    var c = new MockClassElement('C', typeParameters: [u]);
+    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(s.type, v.type),
+        returnType: mapOf(typeParameterType(s), typeParameterType(v)),
         typeParameters: [s, t, v],
         enclosingElement: c);
     FunctionType f = new FunctionTypeImpl(e);
-    var substituted = f.substitute2([objectType], [u.type]);
+    var substituted = f.substitute2([objectType], [typeParameterType(u)]);
     basicChecks(substituted,
         element: same(e),
         displayName: isNotNull,
@@ -867,13 +890,15 @@
     expect(s2.name, 'S');
     expect(t2.name, 'T');
     expect(v2.name, 'V');
-    expect(s2.bound, t2.type);
+    expect(s2.bound, typeParameterType(t2));
     expect(t2.bound, same(objectType));
-    expect(v2.bound, t2.type);
+    expect(v2.bound, typeParameterType(t2));
     if (bug_33301_fixed) {
-      expect(substituted.returnType, mapOf(s2.type, v2.type));
+      expect(substituted.returnType,
+          mapOf(typeParameterType(s2), typeParameterType(v2)));
     } else {
-      expect(substituted.returnType, mapOf(s.type, v.type));
+      expect(substituted.returnType,
+          mapOf(typeParameterType(s), typeParameterType(v)));
     }
   }
 
@@ -881,23 +906,23 @@
     // abstract class C<T> {
     //   void f<S extends T, T extends U, V extends T>(S x, V y);
     // }
-    var s = new MockTypeParameterElement('S');
-    var t = new MockTypeParameterElement('T');
-    var u = new MockTypeParameterElement('U');
-    var v = new MockTypeParameterElement('V');
-    s.bound = t.type;
-    t.bound = u.type;
-    v.bound = t.type;
-    var c = new MockClassElement('C', typeParameters: [u]);
-    var x = new MockParameterElement('x', type: s.type);
-    var y = new MockParameterElement('y', type: v.type);
+    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], [u.type]);
+    var substituted = f.substitute2([objectType], [typeParameterType(u)]);
     basicChecks(substituted,
         element: same(e),
         displayName: isNotNull,
@@ -921,13 +946,15 @@
     expect(s2.name, 'S');
     expect(t2.name, 'T');
     expect(v2.name, 'V');
-    expect(s2.bound, t2.type);
+    expect(s2.bound, typeParameterType(t2));
     expect(t2.bound, same(objectType));
-    expect(v2.bound, t2.type);
+    expect(v2.bound, typeParameterType(t2));
     if (bug_33301_fixed) {
-      expect(substituted.normalParameterTypes, [same(s2.type), same(v2.type)]);
+      expect(substituted.normalParameterTypes,
+          [same(typeParameterType(s2)), same(typeParameterType(v2))]);
     } else {
-      expect(substituted.normalParameterTypes, [same(s.type), same(v.type)]);
+      expect(substituted.normalParameterTypes,
+          [typeParameterType(s), typeParameterType(v)]);
     }
   }
 
@@ -935,13 +962,15 @@
     // abstract class C<T> {
     //   U f<U extends T>();
     // }
-    var t = new MockTypeParameterElement('T');
-    var c = new MockClassElement('C', typeParameters: [t]);
-    var u = new MockTypeParameterElement('U', bound: t.type);
+    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: u.type, enclosingElement: c);
+        typeParameters: [u],
+        returnType: typeParameterType(u),
+        enclosingElement: c);
     FunctionType f = new FunctionTypeImpl(e);
-    var substituted = f.substitute2([objectType], [t.type]);
+    var substituted = f.substitute2([objectType], [typeParameterType(t)]);
     basicChecks(substituted,
         element: same(e),
         displayName: 'U Function<U extends Object>()',
@@ -956,24 +985,25 @@
   }
 
   test_unnamedConstructor_substitute_noop() {
-    var t = new MockTypeParameterElement('T');
-    var e = new MockFunctionTypedElement(returnType: t.type);
+    var t = typeParameter('T');
+    var e = new MockFunctionTypedElement(returnType: typeParameterType(t));
     FunctionType f = new FunctionTypeImpl(e);
-    var substituted = f.substitute2([t.type], [t.type]);
+    var substituted =
+        f.substitute2([typeParameterType(t)], [typeParameterType(t)]);
     basicChecks(substituted,
         element: same(e),
         displayName: 'T Function()',
-        returnType: same(t.type));
+        returnType: typeParameterType(t));
     // TODO(paulberry): test substitute length mismatch
   }
 
   test_unnamedConstructor_substitute_parameterType_simple() {
-    var t = new MockTypeParameterElement('T');
-    var c = new MockClassElement('C', typeParameters: [t]);
-    var p = new MockParameterElement('x', type: t.type);
+    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], [t.type]);
+    var substituted = f.substitute2([objectType], [typeParameterType(t)]);
     basicChecks(substituted,
         element: same(e),
         displayName: 'dynamic Function(Object)',
@@ -987,12 +1017,12 @@
   }
 
   test_unnamedConstructor_substitute_returnType_simple() {
-    var t = new MockTypeParameterElement('T');
-    var c = new MockClassElement('C', typeParameters: [t]);
-    var e =
-        new MockFunctionTypedElement(returnType: t.type, enclosingElement: c);
+    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], [t.type]);
+    var substituted = f.substitute2([objectType], [typeParameterType(t)]);
     basicChecks(substituted,
         element: same(e),
         displayName: 'Object Function()',
@@ -1002,7 +1032,7 @@
   }
 
   test_unnamedConstructor_typeParameter() {
-    var t = new MockTypeParameterElement('T');
+    var t = typeParameter('T');
     var e = new MockFunctionTypedElement(typeParameters: [t]);
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
@@ -1013,72 +1043,40 @@
   }
 
   test_unnamedConstructor_typeParameter_with_bound() {
-    var t = new MockTypeParameterElement('T');
-    var c = new MockClassElement('C', typeParameters: [t]);
-    var u = new MockTypeParameterElement('U', bound: t.type);
+    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: u.type, enclosingElement: c);
+        typeParameters: [u],
+        returnType: typeParameterType(u),
+        enclosingElement: c);
     FunctionType f = new FunctionTypeImpl(e);
     basicChecks(f,
         element: same(e),
         displayName: 'U Function<U extends T>()',
-        typeArguments: [same(t.type)],
+        typeArguments: [typeParameterType(t)],
         typeParameters: [same(t)],
-        returnType: same(u.type),
+        returnType: typeParameterType(u),
         typeFormals: hasLength(1));
     expect(f.typeFormals[0].name, 'U');
-    expect(f.typeFormals[0].bound, same(t.type));
+    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 = new MockTypeParameterElement('T');
-    var c = new MockClassElement('C', typeParameters: [t]);
-    var e =
-        new MockFunctionTypedElement(returnType: t.type, enclosingElement: c);
+    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: same(t.type),
-        typeArguments: [same(t.type)],
+        returnType: typeParameterType(t),
+        typeArguments: [typeParameterType(t)],
         typeParameters: [same(t)]);
   }
-
-  static InterfaceTypeImpl _makeListType() {
-    var e = new MockTypeParameterElement('E');
-    return new InterfaceTypeImpl.elementWithNameAndArgs(
-        new MockClassElement('List', typeParameters: [e]),
-        'List',
-        () => [e.type]);
-  }
-
-  static InterfaceTypeImpl _makeMapType() {
-    var k = new MockTypeParameterElement('K');
-    var v = new MockTypeParameterElement('V');
-    return new InterfaceTypeImpl.elementWithNameAndArgs(
-        new MockClassElement('Map', typeParameters: [k, v]),
-        'Map',
-        () => [k.type, v.type]);
-  }
-}
-
-class MockClassElement implements ClassElementImpl {
-  @override
-  final List<TypeParameterElement> typeParameters;
-
-  @override
-  final String displayName;
-
-  MockClassElement(this.displayName, {this.typeParameters: const []});
-
-  @override
-  get enclosingElement => const MockCompilationUnitElement();
-
-  noSuchMethod(Invocation invocation) {
-    return super.noSuchMethod(invocation);
-  }
 }
 
 class MockCompilationUnitElement implements CompilationUnitElement {
@@ -1092,12 +1090,6 @@
   }
 }
 
-class MockElementLocation implements ElementLocation {
-  noSuchMethod(Invocation invocation) {
-    return super.noSuchMethod(invocation);
-  }
-}
-
 class MockFunctionTypedElement implements FunctionTypedElement {
   @override
   final List<ParameterElement> parameters;
@@ -1129,81 +1121,6 @@
   }
 }
 
-class MockGenericFunctionTypeElementImpl
-    implements GenericFunctionTypeElementImpl {
-  @override
-  final MockGenericTypeAliasElement enclosingElement;
-
-  FunctionTypeImpl _type;
-
-  MockGenericFunctionTypeElementImpl(this.enclosingElement);
-
-  @override
-  get parameters => enclosingElement.parameters;
-
-  @override
-  get returnType => enclosingElement.returnType;
-
-  @override
-  get type => _type ??= new FunctionTypeImpl(this);
-
-  @override
-  get typeParameters => enclosingElement.innerTypeParameters;
-
-  noSuchMethod(Invocation invocation) {
-    return super.noSuchMethod(invocation);
-  }
-}
-
-class MockGenericTypeAliasElement implements GenericTypeAliasElement {
-  @override
-  final String name;
-
-  @override
-  List<ParameterElement> parameters;
-
-  @override
-  final List<TypeParameterElement> typeParameters;
-
-  @override
-  DartType returnType;
-
-  FunctionType _type;
-
-  MockGenericFunctionTypeElementImpl _function;
-
-  final List<TypeParameterElement> innerTypeParameters;
-
-  MockGenericTypeAliasElement(this.name,
-      {this.parameters: const [],
-      DartType returnType,
-      this.typeParameters: const [],
-      this.innerTypeParameters: const []})
-      : returnType = returnType ?? dynamicType;
-
-  MockGenericTypeAliasElement.withNullReturn(this.name,
-      {this.parameters: const [],
-      this.typeParameters: const [],
-      this.innerTypeParameters: const []})
-      : returnType = null;
-
-  @override
-  get enclosingElement => const MockCompilationUnitElement();
-
-  @override
-  get function => _function ??= new MockGenericFunctionTypeElementImpl(this);
-
-  @override
-  get isSynthetic => false;
-
-  @override
-  FunctionType get type => _type ??= new FunctionTypeImpl.forTypedef(this);
-
-  noSuchMethod(Invocation invocation) {
-    return super.noSuchMethod(invocation);
-  }
-}
-
 class MockLibraryElement implements LibraryElement {
   const MockLibraryElement();
 
@@ -1214,77 +1131,3 @@
     return super.noSuchMethod(invocation);
   }
 }
-
-class MockMethodElement extends MockFunctionTypedElement
-    implements MethodElement {
-  @override
-  final bool isStatic;
-
-  MockMethodElement(MockClassElement enclosingElement,
-      {this.isStatic: false, DartType returnType})
-      : super(enclosingElement: enclosingElement, returnType: returnType);
-
-  @override
-  ClassElement get enclosingElement => super.enclosingElement;
-}
-
-class MockParameterElement
-    with ParameterElementMixin
-    implements ParameterElementImpl {
-  @override
-  Element enclosingElement;
-
-  @override
-  final bool isCovariant;
-
-  @override
-  final String name;
-
-  @override
-  final ParameterKind parameterKind;
-
-  @override
-  final DartType type;
-
-  MockParameterElement(this.name,
-      {this.parameterKind: ParameterKind.REQUIRED,
-      this.type,
-      this.isCovariant = false});
-
-  @override
-  get displayName => name;
-
-  noSuchMethod(Invocation invocation) {
-    return super.noSuchMethod(invocation);
-  }
-}
-
-class MockTypeParameterElement implements TypeParameterElement {
-  @override
-  final String name;
-
-  TypeParameterTypeImpl _type;
-
-  MockElementLocation _location;
-
-  @override
-  DartType bound;
-
-  MockTypeParameterElement(this.name, {this.bound});
-
-  @override
-  get kind => ElementKind.TYPE_PARAMETER;
-
-  @override
-  get location => _location ??= new MockElementLocation();
-
-  @override
-  get type => _type ??= new TypeParameterTypeImpl(this);
-
-  noSuchMethod(Invocation invocation) {
-    return super.noSuchMethod(invocation);
-  }
-
-  @override
-  toString() => name;
-}
diff --git a/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart b/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart
index 6286672..71b0757 100644
--- a/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart
+++ b/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
 import 'package:meta/meta.dart';
@@ -1154,7 +1155,7 @@
     @required String name,
     String expected,
   }) {
-    var interfaceType = findElement.classOrMixin(className).type;
+    var interfaceType = _classInterfaceType(className);
 
     var memberType = manager.getInherited(
       interfaceType,
@@ -1171,7 +1172,7 @@
     bool concrete = false,
     bool forSuper = false,
   }) {
-    var interfaceType = findElement.classOrMixin(className).type;
+    var interfaceType = _classInterfaceType(className);
 
     var memberType = manager.getMember(
       interfaceType,
@@ -1184,13 +1185,13 @@
   }
 
   void _assertInheritedConcreteMap(String className, String expected) {
-    var type = findElement.class_(className).type;
+    var type = _classInterfaceType(className);
     var map = manager.getInheritedConcreteMap(type);
     _assertNameToFunctionTypeMap(map, expected);
   }
 
   void _assertInheritedMap(String className, String expected) {
-    var type = findElement.class_(className).type;
+    var type = _classInterfaceType(className);
     var map = manager.getInheritedMap(type);
     _assertNameToFunctionTypeMap(map, expected);
   }
@@ -1227,4 +1228,12 @@
     }
     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 f07f824..3a5221c 100644
--- a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
+++ b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
@@ -3,6 +3,8 @@
 // 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/inheritance_manager3.dart';
 import 'package:meta/meta.dart';
 import 'package:test/test.dart';
@@ -1165,7 +1167,7 @@
     @required String name,
     String expected,
   }) {
-    var interfaceType = findElement.classOrMixin(className).type;
+    var interfaceType = _classInterfaceType(className);
 
     var member = manager.getInherited(
       interfaceType,
@@ -1182,7 +1184,7 @@
     bool concrete = false,
     bool forSuper = false,
   }) {
-    var interfaceType = findElement.classOrMixin(className).type;
+    var interfaceType = _classInterfaceType(className);
 
     var memberType = manager.getMember(
       interfaceType,
@@ -1195,13 +1197,13 @@
   }
 
   void _assertInheritedConcreteMap(String className, String expected) {
-    var type = findElement.class_(className).type;
+    var type = _classInterfaceType(className);
     var map = manager.getInheritedConcreteMap(type);
     _assertNameToExecutableMap(map, expected);
   }
 
   void _assertInheritedMap(String className, String expected) {
-    var type = findElement.class_(className).type;
+    var type = _classInterfaceType(className);
     var map = manager.getInheritedMap(type);
     _assertNameToExecutableMap(map, expected);
   }
@@ -1227,4 +1229,12 @@
     }
     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/least_upper_bound_helper_test.dart b/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
index 13d9100..d9f6283 100644
--- a/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
+++ b/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
@@ -5,14 +5,13 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/type.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/type_system.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../../../generated/test_support.dart';
+import '../../../generated/elements_types_mixin.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -21,17 +20,8 @@
 }
 
 @reflectiveTest
-class InterfaceLeastUpperBoundHelperTest extends EngineTestCase {
-  /**
-   * The type provider used to access the types.
-   */
-  TestTypeProvider _typeProvider;
-
-  @override
-  void setUp() {
-    super.setUp();
-    _typeProvider = new TestTypeProvider();
-  }
+class InterfaceLeastUpperBoundHelperTest with ElementsTypesMixin {
+  final TestTypeProvider typeProvider = TestTypeProvider();
 
   void test_computeLongestInheritancePathToObject_multipleInterfacePaths() {
     //
@@ -50,10 +40,13 @@
     ClassElementImpl classC = ElementFactory.classElement2("C");
     ClassElementImpl classD = ElementFactory.classElement2("D");
     ClassElementImpl classE = ElementFactory.classElement2("E");
-    classB.interfaces = <InterfaceType>[classA.type];
-    classC.interfaces = <InterfaceType>[classA.type];
-    classD.interfaces = <InterfaceType>[classC.type];
-    classE.interfaces = <InterfaceType>[classB.type, classD.type];
+    classB.interfaces = <InterfaceType>[interfaceType(classA)];
+    classC.interfaces = <InterfaceType>[interfaceType(classA)];
+    classD.interfaces = <InterfaceType>[interfaceType(classC)];
+    classE.interfaces = <InterfaceType>[
+      interfaceType(classB),
+      interfaceType(classD)
+    ];
     // assertion: even though the longest path to Object for typeB is 2, and
     // typeE implements typeB, the longest path for typeE is 4 since it also
     // implements typeD
@@ -74,11 +67,15 @@
     //     E
     //
     ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classB = ElementFactory.classElement("B", classA.type);
-    ClassElement classC = ElementFactory.classElement("C", classA.type);
-    ClassElement classD = ElementFactory.classElement("D", classC.type);
-    ClassElementImpl classE = ElementFactory.classElement("E", classB.type);
-    classE.interfaces = <InterfaceType>[classD.type];
+    ClassElement classB =
+        ElementFactory.classElement("B", interfaceType(classA));
+    ClassElement classC =
+        ElementFactory.classElement("C", interfaceType(classA));
+    ClassElement classD =
+        ElementFactory.classElement("D", interfaceType(classC));
+    ClassElementImpl classE =
+        ElementFactory.classElement("E", interfaceType(classB));
+    classE.interfaces = <InterfaceType>[interfaceType(classD)];
     // assertion: even though the longest path to Object for typeB is 2, and
     // typeE extends typeB, the longest path for typeE is 4 since it also
     // implements typeD
@@ -87,13 +84,14 @@
   }
 
   void test_computeLongestInheritancePathToObject_object() {
-    expect(_longestPathToObject(_typeProvider.objectType.element), 0);
+    expect(_longestPathToObject(typeProvider.objectType.element), 0);
   }
 
   void test_computeLongestInheritancePathToObject_recursion() {
     ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
-    classA.supertype = classB.type;
+    ClassElementImpl classB =
+        ElementFactory.classElement("B", interfaceType(classA));
+    classA.supertype = interfaceType(classB);
     expect(_longestPathToObject(classA), 2);
   }
 
@@ -110,8 +108,8 @@
     ClassElementImpl classA = ElementFactory.classElement2("A");
     ClassElementImpl classB = ElementFactory.classElement2("B");
     ClassElementImpl classC = ElementFactory.classElement2("C");
-    classB.interfaces = <InterfaceType>[classA.type];
-    classC.interfaces = <InterfaceType>[classB.type];
+    classB.interfaces = <InterfaceType>[interfaceType(classA)];
+    classC.interfaces = <InterfaceType>[interfaceType(classB)];
     expect(_longestPathToObject(classA), 1);
     expect(_longestPathToObject(classB), 2);
     expect(_longestPathToObject(classC), 3);
@@ -128,8 +126,10 @@
     //     C
     //
     ClassElement classA = ElementFactory.classElement2("A");
-    ClassElement classB = ElementFactory.classElement("B", classA.type);
-    ClassElement classC = ElementFactory.classElement("C", classB.type);
+    ClassElement classB =
+        ElementFactory.classElement("B", interfaceType(classA));
+    ClassElement classC =
+        ElementFactory.classElement("C", interfaceType(classB));
     expect(_longestPathToObject(classA), 1);
     expect(_longestPathToObject(classB), 2);
     expect(_longestPathToObject(classC), 3);
@@ -146,35 +146,31 @@
     //  D
     //
 
-    var instObject = InstantiatedClass.of(_typeProvider.objectType);
+    var instObject = InstantiatedClass.of(typeProvider.objectType);
 
-    ClassElementImpl classA = ElementFactory.classElement2('A');
+    ClassElementImpl classA = class_(name: 'A');
     var instA = InstantiatedClass(classA, const []);
 
-    var classB = ElementFactory.classElement3(
+    var BT = typeParameter('T');
+    var classB = class_(
       name: 'B',
-      typeParameterNames: ['T'],
+      typeParameters: [BT],
       interfaces: [instA.withNullabilitySuffixNone],
     );
 
-    var typeParametersC = ElementFactory.typeParameters(['T']);
-    var classC = ElementFactory.classElement3(
-      name: 'B',
-      typeParameters: typeParametersC,
+    var CT = typeParameter('T');
+    var classC = class_(
+      name: 'C',
+      typeParameters: [CT],
       interfaces: [
         InstantiatedClass(
           classB,
-          [typeParametersC[0].type],
+          [typeParameterType(CT)],
         ).withNullabilitySuffixNone,
       ],
     );
 
-    var classD = ElementFactory.classElement2('D');
-
-    InterfaceTypeImpl typeBT = new InterfaceTypeImpl(classB);
-    DartType typeT = classC.type.typeArguments[0];
-    typeBT.typeArguments = <DartType>[typeT];
-    classC.interfaces = <InterfaceType>[typeBT];
+    var classD = class_(name: 'D');
 
     // A
     expect(
@@ -185,7 +181,7 @@
     // B<D>
     expect(
       _superInterfaces(
-        InstantiatedClass(classB, [classD.type]),
+        InstantiatedClass(classB, [interfaceType(classD)]),
       ),
       unorderedEquals([instObject, instA]),
     );
@@ -193,12 +189,12 @@
     // C<D>
     expect(
       _superInterfaces(
-        InstantiatedClass(classC, [classD.type]),
+        InstantiatedClass(classC, [interfaceType(classD)]),
       ),
       unorderedEquals([
         instObject,
         instA,
-        InstantiatedClass(classB, [classD.type]),
+        InstantiatedClass(classB, [interfaceType(classD)]),
       ]),
     );
   }
@@ -214,7 +210,7 @@
     //  D
     //
 
-    var instObject = InstantiatedClass.of(_typeProvider.objectType);
+    var instObject = InstantiatedClass.of(typeProvider.objectType);
 
     ClassElementImpl classA = ElementFactory.classElement2('A');
     var instA = InstantiatedClass(classA, const []);
@@ -231,7 +227,7 @@
       typeParameters: typeParametersC,
       supertype: InstantiatedClass(
         classB,
-        [typeParametersC[0].type],
+        [typeParameterType(typeParametersC[0])],
       ).withNullabilitySuffixNone,
     );
 
@@ -246,7 +242,7 @@
     // B<D>
     expect(
       _superInterfaces(
-        InstantiatedClass(classB, [classD.type]),
+        InstantiatedClass(classB, [interfaceType(classD)]),
       ),
       unorderedEquals([instObject, instA]),
     );
@@ -254,18 +250,18 @@
     // C<D>
     expect(
       _superInterfaces(
-        InstantiatedClass(classC, [classD.type]),
+        InstantiatedClass(classC, [interfaceType(classD)]),
       ),
       unorderedEquals([
         instObject,
         instA,
-        InstantiatedClass(classB, [classD.type]),
+        InstantiatedClass(classB, [interfaceType(classD)]),
       ]),
     );
   }
 
   void test_computeSuperinterfaceSet_mixin_constraints() {
-    var instObject = InstantiatedClass.of(_typeProvider.objectType);
+    var instObject = InstantiatedClass.of(typeProvider.objectType);
 
     var classA = ElementFactory.classElement3(name: 'A');
     var instA = InstantiatedClass(classA, const []);
@@ -295,7 +291,7 @@
   }
 
   void test_computeSuperinterfaceSet_mixin_constraints_object() {
-    var instObject = InstantiatedClass.of(_typeProvider.objectType);
+    var instObject = InstantiatedClass.of(typeProvider.objectType);
 
     var mixinM = ElementFactory.mixinElement(name: 'M');
     var instM = InstantiatedClass(mixinM, const []);
@@ -307,7 +303,7 @@
   }
 
   void test_computeSuperinterfaceSet_mixin_interfaces() {
-    var instObject = InstantiatedClass.of(_typeProvider.objectType);
+    var instObject = InstantiatedClass.of(typeProvider.objectType);
 
     var classA = ElementFactory.classElement3(name: 'A');
     var instA = InstantiatedClass(classA, const []);
@@ -337,7 +333,7 @@
   }
 
   void test_computeSuperinterfaceSet_multipleInterfacePaths() {
-    var instObject = InstantiatedClass.of(_typeProvider.objectType);
+    var instObject = InstantiatedClass.of(typeProvider.objectType);
 
     var classA = ElementFactory.classElement3(name: 'A');
     var instA = InstantiatedClass(classA, const []);
@@ -383,7 +379,7 @@
   }
 
   void test_computeSuperinterfaceSet_multipleSuperclassPaths() {
-    var instObject = InstantiatedClass.of(_typeProvider.objectType);
+    var instObject = InstantiatedClass.of(typeProvider.objectType);
 
     var classA = ElementFactory.classElement3(name: 'A');
     var instA = InstantiatedClass(classA, const []);
@@ -452,7 +448,7 @@
   }
 
   void test_computeSuperinterfaceSet_singleInterfacePath() {
-    var instObject = InstantiatedClass.of(_typeProvider.objectType);
+    var instObject = InstantiatedClass.of(typeProvider.objectType);
 
     var classA = ElementFactory.classElement3(name: 'A');
     var instA = InstantiatedClass(classA, const []);
@@ -496,7 +492,7 @@
     //  |
     //  C
     //
-    var instObject = InstantiatedClass.of(_typeProvider.objectType);
+    var instObject = InstantiatedClass.of(typeProvider.objectType);
 
     var classA = ElementFactory.classElement3(name: 'A');
     var instA = InstantiatedClass(classA, const []);
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 0069fd1..93095da 100644
--- a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
+++ b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
@@ -6,10 +6,11 @@
 import 'package:analyzer/dart/element/type.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';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../resolution/driver_resolution.dart';
+import '../../../generated/elements_types_mixin.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -22,14 +23,14 @@
 }
 
 @reflectiveTest
-class SubstituteEmptyTest extends DriverResolutionTest {
+class SubstituteEmptyTest extends _Base {
   test_interface() async {
-    addTestFile(r'''
-class A<T> {}
-''');
-    await resolveTestFile();
+    // class A<T> {}
+    var T = typeParameter('T');
+    var A = class_(name: 'A', typeParameters: [T]);
 
-    var type = findElement.class_('A').type;
+    var type = interfaceType(A, typeArguments: [intType]);
+
     var result = Substitution.empty.substituteType(type);
     expect(result, same(type));
   }
@@ -38,21 +39,19 @@
 @reflectiveTest
 class SubstituteFromInterfaceTypeTest extends _Base {
   test_interface() async {
-    addTestFile(r'''
-class A<T> {}
-class B<U> extends A<U> {}
-''');
-    await resolveTestFile();
+    // class A<T> {}
+    var T = typeParameter('T');
+    var A = class_(name: 'A', typeParameters: [T]);
 
-    var a = findElement.class_('A');
-    var b = findElement.class_('B');
-    var u = b.typeParameters.single;
+    // class B<U>  {}
+    var U = typeParameter('U');
+    var B = class_(name: 'B', typeParameters: [U]);
 
-    var bType = _instantiate(b, [intType]);
-    var substitution = Substitution.fromInterfaceType(bType);
+    var BofInt = interfaceType(B, typeArguments: [intType]);
+    var substitution = Substitution.fromInterfaceType(BofInt);
 
-    // `extends A<U>`
-    var type = _instantiate(a, [u.type]);
+    // A<U>
+    var type = interfaceType(A, typeArguments: [typeParameterType(U)]);
     assertElementTypeString(type, 'A<U>');
 
     var result = substitution.substituteType(type);
@@ -61,188 +60,209 @@
 }
 
 @reflectiveTest
-class SubstituteFromPairsTest extends DriverResolutionTest {
+class SubstituteFromPairsTest extends _Base {
   test_interface() async {
-    addTestFile(r'''
-class A<T, U> {}
-''');
-    await resolveTestFile();
+    // class A<T, U> {}
+    var T = typeParameter('T');
+    var U = typeParameter('U');
+    var A = class_(name: 'A', typeParameters: [T, U]);
 
-    var a = findElement.class_('A');
+    var type = interfaceType(
+      A,
+      typeArguments: [
+        typeParameterType(T),
+        typeParameterType(U),
+      ],
+    );
+
     var result = Substitution.fromPairs(
-      a.typeParameters,
+      [T, U],
       [intType, doubleType],
-    ).substituteType(a.type);
+    ).substituteType(type);
     assertElementTypeString(result, 'A<int, double>');
   }
 }
 
 @reflectiveTest
-class SubstituteFromUpperAndLowerBoundsTest extends DriverResolutionTest {
+class SubstituteFromUpperAndLowerBoundsTest extends _Base {
   test_function() async {
-    addTestFile(r'''
-typedef F<T> = T Function(T);
-''');
-    await resolveTestFile();
-
-    var type = findElement.genericTypeAlias('F').function.type;
-    var t = findElement.typeParameter('T');
+    // T Function(T)
+    var T = typeParameter('T');
+    var type = functionType(
+      required: [typeParameterType(T)],
+      returns: typeParameterType(T),
+    );
 
     var result = Substitution.fromUpperAndLowerBounds(
-      {t: intType},
-      {t: BottomTypeImpl.instance},
+      {T: typeProvider.intType},
+      {T: BottomTypeImpl.instance},
     ).substituteType(type);
-    assertElementTypeString(result, 'int Function(Never)');
+    expect(result.toString(), 'int Function(Never)');
   }
 }
 
 @reflectiveTest
 class SubstituteTest extends _Base {
   test_bottom() async {
-    addTestFile(r'''
-class A<T> {}
-''');
-    await resolveTestFile();
-
-    var t = findElement.typeParameter('T');
-    _assertIdenticalType(typeProvider.bottomType, {t: intType});
+    var T = typeParameter('T');
+    _assertIdenticalType(typeProvider.bottomType, {T: intType});
   }
 
   test_dynamic() async {
-    addTestFile(r'''
-class A<T> {}
-''');
-    await resolveTestFile();
-
-    var t = findElement.typeParameter('T');
-    _assertIdenticalType(typeProvider.dynamicType, {t: intType});
+    var T = typeParameter('T');
+    _assertIdenticalType(typeProvider.dynamicType, {T: intType});
   }
 
-  test_function_noTypeParameters() async {
-    addTestFile(r'''
-typedef F = bool Function(int);
-class B<T> {}
-''');
-    await resolveTestFile();
+  test_function_noSubstitutions() async {
+    var type = functionType(required: [intType], returns: boolType);
 
-    var type = findElement.genericTypeAlias('F').function.type;
-    var t = findElement.typeParameter('T');
-    _assertIdenticalType(type, {t: intType});
+    var T = typeParameter('T');
+    _assertIdenticalType(type, {T: intType});
   }
 
-  test_function_typeFormals() async {
-    addTestFile(r'''
-typedef F<T> = T Function<U extends T>(U);
-''');
-    await resolveTestFile();
-
-    var type = findElement.genericTypeAlias('F').function.type;
-    var t = findElement.typeParameter('T');
-    assertElementTypeString(type, 'T Function<U extends T>(U)');
-    _assertSubstitution(
-      type,
-      {t: intType},
-      'int Function<U extends int>(U)',
+  test_function_parameters_returnType() async {
+    // typedef F<T, U> = T Function(U u, bool);
+    var T = typeParameter('T');
+    var U = typeParameter('U');
+    var type = functionType(
+      required: [
+        typeParameterType(U),
+        boolType,
+      ],
+      returns: typeParameterType(T),
     );
-  }
 
-  test_function_typeParameters() async {
-    addTestFile(r'''
-typedef F<T, U> = T Function(U u, bool);
-''');
-    await resolveTestFile();
-
-    var type = findElement.genericTypeAlias('F').function.type;
-    var t = findElement.typeParameter('T');
-    var u = findElement.typeParameter('U');
     assertElementTypeString(type, 'T Function(U, bool)');
     _assertSubstitution(
       type,
-      {t: intType},
+      {T: intType},
       'int Function(U, bool)',
     );
     _assertSubstitution(
       type,
-      {t: intType, u: doubleType},
+      {T: intType, U: doubleType},
       'int Function(double, bool)',
     );
   }
 
-  test_interface_arguments() async {
-    addTestFile(r'''
-class A<T> {}
-class B<U> {}
-''');
-    await resolveTestFile();
+  test_function_typeFormals() async {
+    // typedef F<T> = T Function<U extends T>(U);
+    var T = typeParameter('T');
+    var U = typeParameter('U', bound: typeParameterType(T));
+    var type = functionType(
+      typeFormals: [U],
+      required: [
+        typeParameterType(U),
+      ],
+      returns: typeParameterType(T),
+    );
 
-    var a = findElement.class_('A');
-    var u = findElement.typeParameter('U');
-    var uType = new TypeParameterTypeImpl(u);
-
-    var type = _instantiate(a, [uType]);
-    assertElementTypeString(type, 'A<U>');
-    _assertSubstitution(type, {u: intType}, 'A<int>');
-  }
-
-  test_interface_arguments_deep() async {
-    addTestFile(r'''
-class A<T> {}
-class B<U> {}
-''');
-    await resolveTestFile();
-
-    var a = findElement.class_('A');
-    var u = findElement.typeParameter('U');
-    var uType = new TypeParameterTypeImpl(u);
-
-    var type = _instantiate(a, [
-      _instantiate(listElement, [uType])
-    ]);
-    assertElementTypeString(type, 'A<List<U>>');
-    _assertSubstitution(type, {u: intType}, 'A<List<int>>');
-  }
-
-  test_interface_noArguments() async {
-    addTestFile(r'''
-class A {}
-class B<T> {}
-''');
-    await resolveTestFile();
-
-    var a = findElement.class_('A');
-    var t = findElement.typeParameter('T');
-    _assertIdenticalType(a.type, {t: intType});
-  }
-
-  test_interface_noArguments_inArguments() async {
-    addTestFile(r'''
-class A<T> {}
-class B<U> {}
-''');
-    await resolveTestFile();
-
-    var a = findElement.class_('A');
-    var u = findElement.typeParameter('U');
-    _assertIdenticalType(
-      _instantiate(a, [intType]),
-      {u: doubleType},
+    assertElementTypeString(type, 'T Function<U extends T>(U)');
+    _assertSubstitution(
+      type,
+      {T: intType},
+      'int Function<U extends int>(U)',
     );
   }
 
-  test_void() async {
-    addTestFile(r'''
-class A<T> {}
-''');
-    await resolveTestFile();
+  test_function_typeFormals_bounds() async {
+    // class Triple<X, Y, Z> {}
+    // typedef F<V> = bool Function<T extends Triplet<T, U, V>, U>();
+    var classTriplet = class_(name: 'Triple', typeParameters: [
+      typeParameter('X'),
+      typeParameter('Y'),
+      typeParameter('Z'),
+    ]);
 
-    var t = findElement.typeParameter('T');
-    _assertIdenticalType(voidType, {t: intType});
+    var T = typeParameter('T');
+    var U = typeParameter('U');
+    var V = typeParameter('V');
+    T.bound = interfaceType(classTriplet, typeArguments: [
+      typeParameterType(T),
+      typeParameterType(U),
+      typeParameterType(V),
+    ]);
+    var type = functionType(
+      typeFormals: [T, U],
+      returns: boolType,
+    );
+
+    assertElementTypeString(
+      type,
+      'bool Function<T extends Triple<T, U, V>,U>()',
+    );
+
+    var result = substitute(type, {V: intType}) as FunctionType;
+    assertElementTypeString(
+      result,
+      'bool Function<T extends Triple<T, U, int>,U>()',
+    );
+    var T2 = result.typeFormals[0];
+    var U2 = result.typeFormals[1];
+    var T2boundArgs = (T2.bound as InterfaceType).typeArguments;
+    expect((T2boundArgs[0] as TypeParameterType).element, same(T2));
+    expect((T2boundArgs[1] as TypeParameterType).element, same(U2));
+  }
+
+  test_interface_arguments() async {
+    // class A<T> {}
+    var T = typeParameter('T');
+    var A = class_(name: 'A', typeParameters: [T]);
+
+    var U = typeParameter('U');
+    var type = interfaceType(A, typeArguments: [
+      typeParameterType(U),
+    ]);
+
+    assertElementTypeString(type, 'A<U>');
+    _assertSubstitution(type, {U: intType}, 'A<int>');
+  }
+
+  test_interface_arguments_deep() async {
+    var T = typeParameter('T');
+    var A = class_(name: 'A', typeParameters: [T]);
+
+    var U = typeParameter('U');
+    var type = interfaceType(A, typeArguments: [
+      interfaceType(
+        typeProvider.listElement,
+        typeArguments: [
+          typeParameterType(U),
+        ],
+      )
+    ]);
+    assertElementTypeString(type, 'A<List<U>>');
+
+    _assertSubstitution(type, {U: intType}, 'A<List<int>>');
+  }
+
+  test_interface_noArguments() async {
+    // class A {}
+    var A = class_(name: 'A');
+
+    var type = interfaceType(A);
+    var T = typeParameter('T');
+    _assertIdenticalType(type, {T: intType});
+  }
+
+  test_interface_noArguments_inArguments() async {
+    // class A<T> {}
+    var T = typeParameter('T');
+    var A = class_(name: 'A', typeParameters: [T]);
+
+    var type = interfaceType(A, typeArguments: [intType]);
+
+    var U = typeParameter('U');
+    _assertIdenticalType(type, {U: doubleType});
+  }
+
+  test_void() async {
+    var T = typeParameter('T');
+    _assertIdenticalType(typeProvider.voidType, {T: intType});
   }
 
   test_void_emptyMap() async {
-    addTestFile('');
-    await resolveTestFile();
-    _assertIdenticalType(voidType, {});
+    _assertIdenticalType(intType, {});
   }
 
   void _assertIdenticalType(
@@ -261,11 +281,21 @@
   }
 }
 
-class _Base extends DriverResolutionTest {
-  /// Intentionally low-level implementation for creating [InterfaceType]
-  /// for [ClassElement] and type arguments. We just create it explicitly,
-  /// without using `InterfaceType.instantiate()`.
-  InterfaceType _instantiate(ClassElement element, List<DartType> arguments) {
-    return new InterfaceTypeImpl(element)..typeArguments = arguments;
+class _Base with ElementsTypesMixin {
+  final typeProvider = TestTypeProvider();
+
+  InterfaceType get boolType => typeProvider.boolType;
+
+  InterfaceType get doubleType => typeProvider.doubleType;
+
+  InterfaceType get intType => typeProvider.intType;
+
+  /// Whether `DartType.toString()` with nullability should be asked.
+  bool get typeToStringWithNullability => false;
+
+  void assertElementTypeString(DartType type, String expected) {
+    TypeImpl typeImpl = type;
+    expect(typeImpl.toString(withNullability: typeToStringWithNullability),
+        expected);
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
index e75f914..e556a7f 100644
--- a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
@@ -9,7 +9,6 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'driver_resolution.dart';
-import 'resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -18,10 +17,7 @@
 }
 
 @reflectiveTest
-class AssignmentDriverResolutionTest extends DriverResolutionTest
-    with AssignmentResolutionMixin {}
-
-mixin AssignmentResolutionMixin implements ResolutionTest {
+class AssignmentDriverResolutionTest extends DriverResolutionTest {
   test_compound_indexExpression() async {
     addTestFile(r'''
 main() {
diff --git a/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart b/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart
index d1b41ac..1cb1ed5 100644
--- a/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart
@@ -5,7 +5,6 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'driver_resolution.dart';
-import 'resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -14,10 +13,7 @@
 }
 
 @reflectiveTest
-class ClassAliasDriverResolutionTest extends DriverResolutionTest
-    with ClassAliasResolutionMixin {}
-
-mixin ClassAliasResolutionMixin implements ResolutionTest {
+class ClassAliasDriverResolutionTest extends DriverResolutionTest {
   test_defaultConstructor() async {
     addTestFile(r'''
 class A {}
diff --git a/pkg/analyzer/test/src/dart/resolution/class_test.dart b/pkg/analyzer/test/src/dart/resolution/class_test.dart
index 53ff0e9..aaa8176 100644
--- a/pkg/analyzer/test/src/dart/resolution/class_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/class_test.dart
@@ -6,8 +6,8 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../../generated/elements_types_mixin.dart';
 import 'driver_resolution.dart';
-import 'resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -17,9 +17,7 @@
 
 @reflectiveTest
 class ClassDriverResolutionTest extends DriverResolutionTest
-    with ClassResolutionMixin {}
-
-mixin ClassResolutionMixin implements ResolutionTest {
+    with ElementsTypesMixin {
   test_abstractSuperMemberReference_getter() async {
     addTestFile(r'''
 abstract class A {
@@ -209,25 +207,32 @@
     var c = findElement.class_('C');
     var d = findElement.class_('D');
     var e = findElement.class_('E');
+
+    var typeA = interfaceType(a);
+    var typeB = interfaceType(b);
+    var typeC = interfaceType(c);
+    var typeD = interfaceType(d);
+    var typeE = interfaceType(e);
+
     assertElementTypes(
       findElement.class_('X1').allSupertypes,
-      [a.type, objectType],
+      [typeA, objectType],
     );
     assertElementTypes(
       findElement.class_('X2').allSupertypes,
-      [objectType, b.type],
+      [objectType, typeB],
     );
     assertElementTypes(
       findElement.class_('X3').allSupertypes,
-      [a.type, objectType, b.type],
+      [typeA, objectType, typeB],
     );
     assertElementTypes(
       findElement.class_('X4').allSupertypes,
-      [a.type, b.type, objectType, c.type],
+      [typeA, typeB, objectType, typeC],
     );
     assertElementTypes(
       findElement.class_('X5').allSupertypes,
-      [a.type, b.type, c.type, objectType, d.type, e.type],
+      [typeA, typeB, typeC, objectType, typeD, typeE],
     );
   }
 
@@ -250,16 +255,16 @@
     assertElementTypes(
       findElement.class_('X1').allSupertypes,
       [
-        a.type.instantiate([stringType]),
+        interfaceType(a, typeArguments: [stringType]),
         objectType
       ],
     );
     assertElementTypes(
       findElement.class_('X2').allSupertypes,
       [
-        b.type.instantiate([
+        interfaceType(b, typeArguments: [
           stringType,
-          typeProvider.listType.instantiate([intType])
+          interfaceType(listElement, typeArguments: [intType])
         ]),
         objectType
       ],
@@ -267,8 +272,8 @@
     assertElementTypes(
       findElement.class_('X3').allSupertypes,
       [
-        c.type.instantiate([doubleType]),
-        b.type.instantiate([intType, doubleType]),
+        interfaceType(c, typeArguments: [doubleType]),
+        interfaceType(b, typeArguments: [intType, doubleType]),
         objectType
       ],
     );
@@ -290,7 +295,7 @@
     var c = findElement.class_('C');
     assertElementTypes(
       findElement.class_('X').allSupertypes,
-      [a.type, b.type, c.type],
+      [interfaceType(a), interfaceType(b), interfaceType(c)],
     );
   }
 
diff --git a/pkg/analyzer/test/src/dart/resolution/comment_test.dart b/pkg/analyzer/test/src/dart/resolution/comment_test.dart
index c93fc8d..1d275e6 100644
--- a/pkg/analyzer/test/src/dart/resolution/comment_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/comment_test.dart
@@ -5,7 +5,6 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'driver_resolution.dart';
-import 'resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -13,7 +12,8 @@
   });
 }
 
-mixin ClassAliasResolutionMixin implements ResolutionTest {
+@reflectiveTest
+class CommentDriverResolutionTest extends DriverResolutionTest {
   test_error_unqualifiedReferenceToNonLocalStaticMember() async {
     await assertNoErrorsInCode(r'''
 class A {
@@ -223,7 +223,3 @@
     );
   }
 }
-
-@reflectiveTest
-class CommentDriverResolutionTest extends DriverResolutionTest
-    with ClassAliasResolutionMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/constant_test.dart b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
index 6430fc1..fec0505 100644
--- a/pkg/analyzer/test/src/dart/resolution/constant_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
@@ -9,7 +9,6 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'driver_resolution.dart';
-import 'resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -18,9 +17,7 @@
 }
 
 @reflectiveTest
-class ConstantDriverTest extends DriverResolutionTest with ConstantMixin {}
-
-mixin ConstantMixin implements ResolutionTest {
+class ConstantDriverTest extends DriverResolutionTest {
   test_constantValue_defaultParameter_noDefaultValue() async {
     newFile('/test/lib/a.dart', content: r'''
 class A {
diff --git a/pkg/analyzer/test/src/dart/resolution/enum_test.dart b/pkg/analyzer/test/src/dart/resolution/enum_test.dart
index 8e9b10b..f204d72 100644
--- a/pkg/analyzer/test/src/dart/resolution/enum_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/enum_test.dart
@@ -6,7 +6,6 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'driver_resolution.dart';
-import 'resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -15,10 +14,7 @@
 }
 
 @reflectiveTest
-class EnumDriverResolutionTest extends DriverResolutionTest
-    with EnumResolutionMixin {}
-
-mixin EnumResolutionMixin implements ResolutionTest {
+class EnumDriverResolutionTest extends DriverResolutionTest {
   test_inference_listLiteral() async {
     addTestFile(r'''
 enum E1 {a, b}
diff --git a/pkg/analyzer/test/src/dart/resolution/for_in_test.dart b/pkg/analyzer/test/src/dart/resolution/for_in_test.dart
index 4c8f5b8..5b83f62 100644
--- a/pkg/analyzer/test/src/dart/resolution/for_in_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/for_in_test.dart
@@ -6,7 +6,6 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'driver_resolution.dart';
-import 'resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -15,10 +14,7 @@
 }
 
 @reflectiveTest
-class ForInDriverResolutionTest extends DriverResolutionTest
-    with ForInResolutionMixin {}
-
-mixin ForInResolutionMixin implements ResolutionTest {
+class ForInDriverResolutionTest extends DriverResolutionTest {
   test_importPrefix_asIterable() async {
     // TODO(scheglov) Remove this test (already tested as import prefix).
     // TODO(scheglov) Move other for-in tests here.
diff --git a/pkg/analyzer/test/src/dart/resolution/import_prefix_test.dart b/pkg/analyzer/test/src/dart/resolution/import_prefix_test.dart
index b9e9d61..c514779 100644
--- a/pkg/analyzer/test/src/dart/resolution/import_prefix_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/import_prefix_test.dart
@@ -7,7 +7,6 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'driver_resolution.dart';
-import 'resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -16,10 +15,7 @@
 }
 
 @reflectiveTest
-class ImportPrefixDriverResolutionTest extends DriverResolutionTest
-    with ImportPrefixResolutionMixin {}
-
-mixin ImportPrefixResolutionMixin implements ResolutionTest {
+class ImportPrefixDriverResolutionTest extends DriverResolutionTest {
   test_asExpression_expressionStatement() async {
     addTestFile(r'''
 import 'dart:async' as p;
diff --git a/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart b/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
index 2a5fd62..962eb5d 100644
--- a/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
@@ -6,7 +6,6 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'driver_resolution.dart';
-import 'resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -15,10 +14,7 @@
 }
 
 @reflectiveTest
-class InstanceCreationDriverResolutionTest extends DriverResolutionTest
-    with InstanceCreationResolutionMixin {}
-
-mixin InstanceCreationResolutionMixin implements ResolutionTest {
+class InstanceCreationDriverResolutionTest extends DriverResolutionTest {
   test_error_newWithInvalidTypeParameters_implicitNew_inference_top() async {
     addTestFile(r'''
 final foo = Map<int>();
diff --git a/pkg/analyzer/test/src/dart/resolution/instance_member_inference_class_test.dart b/pkg/analyzer/test/src/dart/resolution/instance_member_inference_class_test.dart
index 1faee15..44c13fe 100644
--- a/pkg/analyzer/test/src/dart/resolution/instance_member_inference_class_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/instance_member_inference_class_test.dart
@@ -5,7 +5,6 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'driver_resolution.dart';
-import 'resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -15,9 +14,7 @@
 
 @reflectiveTest
 class InstanceMemberInferenceClassDriverResolutionTest
-    extends DriverResolutionTest with InstanceMemberInferenceClassMixin {}
-
-mixin InstanceMemberInferenceClassMixin implements ResolutionTest {
+    extends DriverResolutionTest {
   test_invalid_inheritanceCycle() async {
     addTestFile('''
 class A extends C {}
diff --git a/pkg/analyzer/test/src/dart/resolution/instance_member_inference_mixin_test.dart b/pkg/analyzer/test/src/dart/resolution/instance_member_inference_mixin_test.dart
index 7c2104f..0368dd9 100644
--- a/pkg/analyzer/test/src/dart/resolution/instance_member_inference_mixin_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/instance_member_inference_mixin_test.dart
@@ -5,7 +5,6 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'driver_resolution.dart';
-import 'resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -15,9 +14,7 @@
 
 @reflectiveTest
 class InstanceMemberInferenceMixinDriverResolutionTest
-    extends DriverResolutionTest with InstanceMemberInferenceMixinMixin {}
-
-mixin InstanceMemberInferenceMixinMixin implements ResolutionTest {
+    extends DriverResolutionTest {
   test_invalid_inheritanceCycle() async {
     addTestFile('''
 mixin A on C {}
diff --git a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
index 68895de..8ebd753 100644
--- a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
@@ -8,6 +8,7 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../../generated/elements_types_mixin.dart';
 import 'driver_resolution.dart';
 
 main() {
@@ -17,7 +18,8 @@
 }
 
 @reflectiveTest
-class MixinDriverResolutionTest extends DriverResolutionTest {
+class MixinDriverResolutionTest extends DriverResolutionTest
+    with ElementsTypesMixin {
   test_accessor_getter() async {
     await assertNoErrorsInCode(r'''
 mixin M {
@@ -92,7 +94,7 @@
     var mElement = findElement.mixin('M');
 
     var aElement = findElement.class_('A');
-    assertElementTypes(aElement.mixins, [mElement.type]);
+    assertElementTypes(aElement.mixins, [interfaceType(mElement)]);
 
     var mRef = findNode.typeName('M {} // A');
     assertTypeName(mRef, mElement, 'M');
@@ -107,7 +109,7 @@
     var mElement = findElement.mixin('M');
 
     var aElement = findElement.class_('A');
-    assertElementTypes(aElement.mixins, [mElement.type]);
+    assertElementTypes(aElement.mixins, [interfaceType(mElement)]);
 
     var mRef = findNode.typeName('M;');
     assertTypeName(mRef, mElement, 'M');
@@ -153,7 +155,8 @@
     expect(element.isEnum, isFalse);
     expect(element.isMixin, isTrue);
     expect(element.isMixinApplication, isFalse);
-    expect(element.type.isObject, isFalse);
+    expect(interfaceType(element).isObject, isFalse);
+    expect(element.isDartCoreObject, isFalse);
 
     assertElementTypes(element.superclassConstraints, [objectType]);
     assertElementTypes(element.interfaces, []);
@@ -174,11 +177,11 @@
     var c = findElement.class_('C');
     assertElementTypes(
       findElement.mixin('M1').allSupertypes,
-      [a.type, b.type, objectType],
+      [interfaceType(a), interfaceType(b), objectType],
     );
     assertElementTypes(
       findElement.mixin('M2').allSupertypes,
-      [a.type, objectType, b.type, c.type],
+      [interfaceType(a), objectType, interfaceType(b), interfaceType(c)],
     );
   }
 
@@ -196,15 +199,15 @@
     assertElementTypes(
       findElement.mixin('M1').allSupertypes,
       [
-        a.type.instantiate([intType, doubleType]),
+        interfaceType(a, typeArguments: [intType, doubleType]),
         objectType
       ],
     );
     assertElementTypes(
       findElement.mixin('M2').allSupertypes,
       [
-        b.type.instantiate([stringType]),
-        a.type.instantiate([intType, stringType]),
+        interfaceType(b, typeArguments: [stringType]),
+        interfaceType(a, typeArguments: [intType, stringType]),
         objectType
       ],
     );
@@ -353,7 +356,7 @@
     var randomElement = mathImport.importedLibrary.getType('Random');
 
     var element = findElement.mixin('M');
-    assertElementTypes(element.interfaces, [randomElement.type]);
+    assertElementTypes(element.interfaces, [interfaceType(randomElement)]);
 
     var typeRef = findNode.typeName('Random {}');
     assertTypeName(typeRef, randomElement, 'Random',
@@ -916,7 +919,9 @@
     var randomElement = mathImport.importedLibrary.getType('Random');
 
     var element = findElement.mixin('M');
-    assertElementTypes(element.superclassConstraints, [randomElement.type]);
+    assertElementTypes(element.superclassConstraints, [
+      interfaceType(randomElement),
+    ]);
 
     var typeRef = findNode.typeName('Random {}');
     assertTypeName(typeRef, randomElement, 'Random',
@@ -993,7 +998,9 @@
 
     var a = findElement.mixin('A');
     var b = findElement.mixin('B');
-    assertElementTypes(b.superclassConstraints, [a.type]);
+    assertElementTypes(b.superclassConstraints, [
+      interfaceType(a),
+    ]);
   }
 
   test_error_onRepeated() async {
@@ -1258,7 +1265,7 @@
 ''');
 
     var element = findElement.mixin('M');
-    var type = element.type;
+    var type = interfaceType(element);
     // ignore: deprecated_member_use_from_same_package
     expect(type.isMoreSpecificThan(intType), isFalse);
   }
diff --git a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
index b4f9586..287b10c 100644
--- a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
@@ -11,7 +11,6 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'driver_resolution.dart';
-import 'resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -20,10 +19,7 @@
 }
 
 @reflectiveTest
-class OptionalConstDriverResolutionTest extends DriverResolutionTest
-    with OptionalConstMixin {}
-
-mixin OptionalConstMixin implements ResolutionTest {
+class OptionalConstDriverResolutionTest extends DriverResolutionTest {
   Map<String, LibraryElement> libraries = {};
 
   LibraryElement get libraryA => libraries['package:test/a.dart'];
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index bae934f..332bcca 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -49,9 +49,9 @@
 
   InterfaceType get intType => typeProvider.intType;
 
-  ClassElement get listElement => typeProvider.listType.element;
+  ClassElement get listElement => typeProvider.listElement;
 
-  ClassElement get mapElement => typeProvider.mapType.element;
+  ClassElement get mapElement => typeProvider.mapElement;
 
   ClassElement get numElement => typeProvider.numType.element;
 
diff --git a/pkg/analyzer/test/src/dart/resolution/top_type_inference_test.dart b/pkg/analyzer/test/src/dart/resolution/top_type_inference_test.dart
index 65de6ba..5e56cac 100644
--- a/pkg/analyzer/test/src/dart/resolution/top_type_inference_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/top_type_inference_test.dart
@@ -6,7 +6,6 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'driver_resolution.dart';
-import 'resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -15,10 +14,7 @@
 }
 
 @reflectiveTest
-class TopTypeInferenceDriverResolutionTest extends DriverResolutionTest
-    with TopTypeInstanceMixin {}
-
-mixin TopTypeInstanceMixin implements ResolutionTest {
+class TopTypeInferenceDriverResolutionTest extends DriverResolutionTest {
   test_referenceInstanceVariable_withDeclaredType() async {
     addTestFile(r'''
 class A {
diff --git a/pkg/analyzer/test/src/dart/resolver/legacy_type_asserter_test.dart b/pkg/analyzer/test/src/dart/resolver/legacy_type_asserter_test.dart
index 2447515..b85f38b 100644
--- a/pkg/analyzer/test/src/dart/resolver/legacy_type_asserter_test.dart
+++ b/pkg/analyzer/test/src/dart/resolver/legacy_type_asserter_test.dart
@@ -4,6 +4,7 @@
 
 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/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/resolver/legacy_type_asserter.dart';
@@ -66,10 +67,9 @@
   test_nullableUnit_expressionStaticType_nonNullTypeArgument() async {
     var identifier = AstTestFactory.identifier3('foo');
     var unit = _wrapExpression(identifier);
-    identifier.staticType = typeProvider.listType.instantiate([
-      (typeProvider.intType as TypeImpl)
-          .withNullability(NullabilitySuffix.question)
-    ]);
+    identifier.staticType = typeProvider.listType2(
+        (typeProvider.intType as TypeImpl)
+            .withNullability(NullabilitySuffix.question));
 
     expect(() {
       LegacyTypeAsserter.assertLegacyTypes(unit);
@@ -79,17 +79,14 @@
   test_nullableUnit_expressionStaticType_nonNullTypeParameter() async {
     var identifier = AstTestFactory.identifier3('foo');
     var unit = _wrapExpression(identifier);
-    final listType = typeProvider.listType;
-    listType.typeParameters[0] = TypeParameterElementImpl('E', 0)
-      ..type = (listType.typeParameters[0].type as TypeImpl)
-          .withNullability(NullabilitySuffix.none) as TypeParameterTypeImpl;
-    identifier.staticType = listType;
-    expect(
-        (listType as dynamic)
-            .typeParameters[0]
-            .type
-            .toString(withNullability: true),
-        'E');
+    identifier.staticType = typeProvider.listElement.instantiate(
+      typeArguments: [
+        TypeParameterElementImpl('E', 0).instantiate(
+          nullabilitySuffix: NullabilitySuffix.none,
+        ),
+      ],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
     expect(() {
       LegacyTypeAsserter.assertLegacyTypes(unit);
     }, throwsStateError);
@@ -98,18 +95,13 @@
   test_nullableUnit_expressionStaticType_nonNullTypeParameterBound() async {
     var identifier = AstTestFactory.identifier3('foo');
     var unit = _wrapExpression(identifier);
-    final listType = typeProvider.listType;
-    (listType.typeParameters[0] as TypeParameterElementImpl).bound =
-        (typeProvider.intType as TypeImpl)
-            .withNullability(NullabilitySuffix.none);
-    identifier.staticType = listType;
-    expect(
-        (listType as dynamic)
-            .typeParameters[0]
-            .type
-            .bound
-            .toString(withNullability: true),
-        'int');
+    var T = TypeParameterElementImpl.synthetic('T');
+    T.bound = (typeProvider.intType as TypeImpl)
+        .withNullability(NullabilitySuffix.none);
+    identifier.staticType = TypeParameterTypeImpl(
+      T,
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
     expect(() {
       LegacyTypeAsserter.assertLegacyTypes(unit);
     }, throwsStateError);
diff --git a/pkg/analyzer/test/src/diagnostics/assignment_to_final_no_setter_test.dart b/pkg/analyzer/test/src/diagnostics/assignment_to_final_no_setter_test.dart
index 238174f..20ed816 100644
--- a/pkg/analyzer/test/src/diagnostics/assignment_to_final_no_setter_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/assignment_to_final_no_setter_test.dart
@@ -12,6 +12,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AssignmentToFinalNoSetterTest);
+    defineReflectiveTests(AssignmentToFinalNoSetterWithExtensionMethodsTest);
   });
 }
 
@@ -47,7 +48,7 @@
 }
 
 @reflectiveTest
-class AssignmentToMethodWithExtensionMethodsTest
+class AssignmentToFinalNoSetterWithExtensionMethodsTest
     extends AssignmentToFinalNoSetterTest {
   @override
   AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
@@ -63,7 +64,7 @@
   0.foo = 1;
 }
 ''', [
-      error(CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER, 53, 3),
+      error(StaticWarningCode.ASSIGNMENT_TO_FINAL_NO_SETTER, 53, 3),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart b/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart
index 8fa1978..93e0972 100644
--- a/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -316,6 +317,15 @@
       error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 56, 3),
     ]);
   }
+
+  test_topLevel_syntheticParameters() async {
+    await assertErrorsInCode(r'''
+f(,[]) {}
+''', [
+      error(ParserErrorCode.MISSING_IDENTIFIER, 2, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 4, 1),
+    ]);
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/diagnostics/extension_override_with_cascade_test.dart b/pkg/analyzer/test/src/diagnostics/extension_override_with_cascade_test.dart
new file mode 100644
index 0000000..b8bcd87
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/extension_override_with_cascade_test.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.
+
+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';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ExtensionOverrideWithCascadeTest);
+  });
+}
+
+@reflectiveTest
+class ExtensionOverrideWithCascadeTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.extension_methods]);
+
+  test_getter() async {
+    await assertErrorsInCode('''
+extension E on int {
+  int get g => 0;
+}
+f() {
+  E(3)..g;
+}
+''', [
+      error(CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE, 53, 2),
+    ]);
+  }
+
+  test_method() async {
+    await assertErrorsInCode('''
+extension E on int {
+  void m() {}
+}
+f() {
+  E(3)..m();
+}
+''', [
+      error(CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE, 49, 2),
+    ]);
+  }
+
+  test_setter() async {
+    await assertErrorsInCode('''
+extension E on int {
+  set s(int i) {}
+}
+f() {
+  E(3)..s = 4;
+}
+''', [
+      error(CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE, 53, 2),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/inference_failure_on_collection_literal_test.dart b/pkg/analyzer/test/src/diagnostics/inference_failure_on_collection_literal_test.dart
new file mode 100644
index 0000000..c73ced5
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/inference_failure_on_collection_literal_test.dart
@@ -0,0 +1,176 @@
+// 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/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InferenceFailureOnCollectionLiteralTest);
+  });
+}
+
+@reflectiveTest
+class InferenceFailureOnCollectionLiteralTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions =>
+      AnalysisOptionsImpl()..strictInference = true;
+
+  test_collectionsWithAnyElements() async {
+    await assertNoErrorsInCode(r'''
+void main() {
+  var a = [7];
+  var b = [7 as dynamic];
+  var c = {7};
+  var d = {7 as dynamic};
+  var e = {7: 42};
+  var f = {7 as dynamic: 42};
+  var g = {7: 42 as dynamic};
+}
+''');
+  }
+
+  test_conditionalList() async {
+    await assertErrorsInCode(r'''
+void main() {
+  var x = "a" == "b" ? [1, 2, 3] : [];
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 20, 1),
+      error(HintCode.INFERENCE_FAILURE_ON_COLLECTION_LITERAL, 49, 2),
+    ]);
+  }
+
+  test_defaultParameter_list() async {
+    await assertErrorsInCode(r'''
+void f([list = const []]) => print(list);
+''', [
+      error(HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER, 8, 4),
+      error(HintCode.INFERENCE_FAILURE_ON_COLLECTION_LITERAL, 15, 8),
+    ]);
+  }
+
+  test_defaultParameter_map() async {
+    await assertErrorsInCode(r'''
+void f([map = const {}]) => print(map);
+''', [
+      error(HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER, 8, 3),
+      error(HintCode.INFERENCE_FAILURE_ON_COLLECTION_LITERAL, 14, 8),
+    ]);
+  }
+
+  test_downwardsInference() async {
+    await assertNoErrorsInCode(r'''
+void main() {
+  List<dynamic> a = [];
+  Set<dynamic> b = {};
+  Map<dynamic, dynamic> c = {};
+
+  int setLength(Set<Object> set) => set.length;
+  setLength({});
+
+  List<int> f() => [];
+  Set<int> g() => {};
+  Map<int, int> h() => {};
+}
+''');
+  }
+
+  test_explicitTypeArguments() async {
+    await assertNoErrorsInCode(r'''
+void main() {
+  var a = <dynamic>[];
+  var b = <dynamic>{};
+  var c = <dynamic, dynamic>{};
+}
+''');
+  }
+
+  test_functionReturnsList_dynamicReturnType() async {
+    await assertErrorsInCode(r'''
+dynamic f() => [];
+''', [
+      error(HintCode.INFERENCE_FAILURE_ON_COLLECTION_LITERAL, 15, 2),
+    ]);
+  }
+
+  test_functionReturnsList_ObjectReturnType() async {
+    await assertNoErrorsInCode(r'''
+Object f() => [];
+''');
+  }
+
+  test_functionReturnsList_voidReturnType() async {
+    await assertNoErrorsInCode(r'''
+void f() => [];
+''');
+  }
+
+  test_inferredFromNullAware() async {
+    await assertNoErrorsInCode(r'''
+void main() {
+  var x = [1, 2, 3] ?? [];
+}
+''');
+  }
+
+  test_localConstVariable_list() async {
+    await assertErrorsInCode(r'''
+void main() {
+  const x = [];
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 22, 1),
+      error(HintCode.INFERENCE_FAILURE_ON_COLLECTION_LITERAL, 26, 2),
+    ]);
+  }
+
+  test_localConstVariable_map() async {
+    await assertErrorsInCode(r'''
+void main() {
+  const x = {};
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 22, 1),
+      error(HintCode.INFERENCE_FAILURE_ON_COLLECTION_LITERAL, 26, 2),
+    ]);
+  }
+
+  test_localVariable_list() async {
+    await assertErrorsInCode(r'''
+void main() {
+  var x = [];
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 20, 1),
+      error(HintCode.INFERENCE_FAILURE_ON_COLLECTION_LITERAL, 24, 2),
+    ]);
+  }
+
+  test_localVariable_map() async {
+    await assertErrorsInCode(r'''
+void main() {
+  var x = {};
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 20, 1),
+      error(HintCode.INFERENCE_FAILURE_ON_COLLECTION_LITERAL, 24, 2),
+    ]);
+  }
+
+  test_onlyInnerMostEmptyCollections() async {
+    await assertErrorsInCode(r'''
+void main() {
+  var x = {[]: {}};
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 20, 1),
+      error(HintCode.INFERENCE_FAILURE_ON_COLLECTION_LITERAL, 25, 2),
+      error(HintCode.INFERENCE_FAILURE_ON_COLLECTION_LITERAL, 29, 2),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/inference_failure_on_function_return_type_test.dart b/pkg/analyzer/test/src/diagnostics/inference_failure_on_function_return_type_test.dart
new file mode 100644
index 0000000..0bcdf0a
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/inference_failure_on_function_return_type_test.dart
@@ -0,0 +1,172 @@
+// 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/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';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InferenceFailureOnFunctionReturnTypeTest);
+    defineReflectiveTests(InferenceFailureOnFunctionReturnType_InExtensionTest);
+  });
+}
+
+@reflectiveTest
+class InferenceFailureOnFunctionReturnType_InExtensionTest
+    extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.extension_methods])
+    ..strictInference = true;
+
+  test_extensionMethod() async {
+    assertErrorsInCode(r'''
+extension E on List {
+  e() {
+    return 7;
+  }
+}
+''', [error(HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE, 24, 23)]);
+  }
+}
+
+/// Tests of HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE with the
+/// "strict-inference" static analysis option.
+@reflectiveTest
+class InferenceFailureOnFunctionReturnTypeTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions =>
+      AnalysisOptionsImpl()..strictInference = true;
+
+  test_classInstanceGetter() async {
+    await assertErrorsInCode(r'''
+class C {
+  get f => 7;
+}
+''', [error(HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE, 12, 11)]);
+  }
+
+  test_classInstanceMethod() async {
+    await assertErrorsInCode(r'''
+class C {
+  f() => 7;
+}
+''', [error(HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE, 12, 9)]);
+  }
+
+  test_classInstanceMethod_withReturnType() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  Object f() => 7;
+}
+''');
+  }
+
+  test_classInstanceOperator() async {
+    await assertErrorsInCode(r'''
+class C {
+  operator +(int x) => print(x);
+}
+''', [error(HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE, 12, 30)]);
+  }
+
+  test_classInstanceSetter() async {
+    await assertErrorsInCode(r'''
+class C {
+  set f(int x) => print(x);
+}
+''', [error(HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE, 12, 25)]);
+  }
+
+  test_classStaticMethod() async {
+    await assertErrorsInCode(r'''
+class C {
+  static f() => 7;
+}
+''', [error(HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE, 12, 16)]);
+  }
+
+  test_classStaticMethod_withType() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  static int f() => 7;
+}
+''');
+  }
+
+  test_functionTypedParameter() async {
+    await assertErrorsInCode(r'''
+void f(callback()) {
+  callback();
+}
+''', [error(HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE, 7, 10)]);
+  }
+
+  test_functionTypedParameter_nested() async {
+    await assertErrorsInCode(r'''
+void f(void callback(callback2())) {
+  callback(() => print('hey'));
+}
+''', [error(HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE, 21, 11)]);
+  }
+
+  test_functionTypedParameter_withReturnType() async {
+    await assertNoErrorsInCode(r'''
+void f(int callback()) {
+  callback();
+}
+''');
+  }
+
+  test_localFunction() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  void f() {
+    g() => 7;
+  }
+}
+''');
+  }
+
+  test_mixinInstanceMethod() async {
+    await assertErrorsInCode(r'''
+mixin C {
+  f() => 7;
+}
+''', [error(HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE, 12, 9)]);
+  }
+
+  test_topLevelArrowFunction() async {
+    await assertErrorsInCode(r'''
+f() => 7;
+''', [error(HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE, 0, 9)]);
+  }
+
+  test_topLevelFunction() async {
+    await assertErrorsInCode(r'''
+f() {
+  return 7;
+}
+''', [error(HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE, 0, 19)]);
+  }
+
+  test_topLevelFunction_async() async {
+    await assertErrorsInCode(r'''
+f() {
+  return 7;
+}
+''', [error(HintCode.INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE, 0, 19)]);
+  }
+
+  test_topLevelFunction_withReturnType() async {
+    await assertNoErrorsInCode(r'''
+dynamic f() => 7;
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/inference_failure_on_uninitialized_variable_test.dart b/pkg/analyzer/test/src/diagnostics/inference_failure_on_uninitialized_variable_test.dart
index 74d1bf6..736554b 100644
--- a/pkg/analyzer/test/src/diagnostics/inference_failure_on_uninitialized_variable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/inference_failure_on_uninitialized_variable_test.dart
@@ -29,7 +29,7 @@
 
   test_localVariable() async {
     String code = r'''
-f() {
+void f() {
   var a;
 }
 ''';
@@ -40,7 +40,7 @@
 
   test_localVariable_withInitializer() async {
     String code = r'''
-f() {
+void f() {
   var a = 7;
 }
 ''';
@@ -50,7 +50,7 @@
 
   test_localVariable_withType() async {
     String code = r'''
-f() {
+void f() {
   int a;
   dynamic b;
   Object c;
diff --git a/pkg/analyzer/test/src/diagnostics/inference_failure_on_untyped_parameter_test.dart b/pkg/analyzer/test/src/diagnostics/inference_failure_on_untyped_parameter_test.dart
index 2199133..e1cf255 100644
--- a/pkg/analyzer/test/src/diagnostics/inference_failure_on_untyped_parameter_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/inference_failure_on_untyped_parameter_test.dart
@@ -212,7 +212,7 @@
 
   test_parameter_inFunctionLiteral() async {
     String code = r'''
-fn() {
+void fn() {
   var f = (var a) {};
 }
 ''';
@@ -223,7 +223,7 @@
 
   test_parameter_inFunctionLiteral_withType() async {
     String code = r'''
-fn() {
+void fn() {
   var f = (int a) {};
 }
 ''';
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
index ab75f79..8ca6262 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
@@ -24,7 +24,7 @@
   String get g { return 'a'; }
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 60, 28),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 71, 1),
     ]);
   }
 
@@ -37,8 +37,8 @@
   int f;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 46, 5),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 46, 5),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 50, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 50, 1),
     ]);
   }
 
@@ -56,8 +56,8 @@
   String get getter => null;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 152, 26),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 152, 26),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 163, 6),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 163, 6),
     ]);
   }
 
@@ -73,8 +73,22 @@
   double get g => null;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 127, 21),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 127, 21),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 138, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 138, 1),
+    ]);
+  }
+
+  test_method_abstractOverridesConcrete() async {
+    await assertErrorsInCode('''
+class A	{
+  int add(int a, int b) => a + b;
+}
+class B	extends A {
+  int add();
+}
+''', [
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 52, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 72, 3),
     ]);
   }
 
@@ -87,7 +101,7 @@
   m({a}) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 49, 9),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 49, 1),
     ]);
   }
 
@@ -100,7 +114,7 @@
   m({a, c}) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 49, 12),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 49, 1),
     ]);
   }
 
@@ -113,7 +127,7 @@
   m({String a}) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 53, 16),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 53, 1),
     ]);
   }
 
@@ -126,7 +140,7 @@
   m(String a) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 51, 14),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 51, 1),
     ]);
   }
 
@@ -139,7 +153,7 @@
   m(String a) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 48, 14),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 48, 1),
     ]);
   }
 
@@ -155,8 +169,8 @@
   m(double d) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 132, 14),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 132, 14),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 132, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 132, 1),
     ]);
   }
 
@@ -173,8 +187,8 @@
   m(String n) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 124, 14),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 124, 14),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 124, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 124, 1),
     ]);
   }
 
@@ -191,8 +205,8 @@
   m(double d) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 125, 14),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 125, 14),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 125, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 125, 1),
     ]);
   }
 
@@ -205,7 +219,7 @@
   m([String a]) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 53, 16),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 53, 1),
     ]);
   }
 
@@ -222,8 +236,8 @@
   m([String n]) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 128, 16),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 128, 16),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 128, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 128, 1),
     ]);
   }
 
@@ -236,7 +250,7 @@
   m([a]) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 49, 9),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 49, 1),
     ]);
   }
 
@@ -249,7 +263,7 @@
   m(a, b, [c]) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 55, 15),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 55, 1),
     ]);
   }
 
@@ -262,7 +276,7 @@
   m(a, [c, d]) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 55, 15),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 55, 1),
     ]);
   }
 
@@ -275,7 +289,7 @@
   m(a, b) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 44, 10),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 44, 1),
     ]);
   }
 
@@ -288,7 +302,7 @@
   String m() { return 'a'; }
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 61, 26),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 68, 1),
     ]);
   }
 
@@ -303,7 +317,7 @@
   String m() { return 'a'; }
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 91, 26),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 98, 1),
     ]);
   }
 
@@ -316,7 +330,7 @@
   String m() { return 'a'; }
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 70, 26),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 77, 1),
     ]);
   }
 
@@ -329,7 +343,7 @@
   String m() { return 'a'; }
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 58, 26),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 65, 1),
     ]);
   }
 
@@ -344,7 +358,7 @@
   String m() { return 'a'; }
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 80, 26),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 87, 1),
     ]);
   }
 
@@ -361,8 +375,8 @@
   String m() => '';
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 122, 17),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 122, 17),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 129, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 129, 1),
     ]);
   }
 
@@ -375,7 +389,7 @@
   void m() {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 58, 11),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 63, 1),
     ]);
   }
 
@@ -388,7 +402,7 @@
   void set s(String v) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 57, 23),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 66, 1),
     ]);
   }
 
@@ -405,8 +419,8 @@
   set setter14(String _) => null;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 169, 31),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 169, 31),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 173, 8),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 173, 8),
     ]);
   }
 
@@ -424,8 +438,8 @@
   set setter14(String _) => null;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 162, 31),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 162, 31),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 166, 8),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 166, 8),
     ]);
   }
 
@@ -441,8 +455,8 @@
   set s(double d) {}
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 121, 18),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 121, 18),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 125, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 125, 1),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_field_test.dart b/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_field_test.dart
index 2a978fe..cb18626 100644
--- a/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_field_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/override_on_non_overriding_field_test.dart
@@ -30,7 +30,7 @@
   @override
   int c;
 }''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 126, 5),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 130, 1),
     ]);
   }
 
@@ -49,7 +49,7 @@
   @override
   int c;
 }''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 123, 5),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 127, 1),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/static_access_to_instance_member_test.dart b/pkg/analyzer/test/src/diagnostics/static_access_to_instance_member_test.dart
index 6fc3e81..b9b0063 100644
--- a/pkg/analyzer/test/src/diagnostics/static_access_to_instance_member_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/static_access_to_instance_member_test.dart
@@ -11,13 +11,73 @@
 
 main() {
   defineReflectiveSuite(() {
-//    defineReflectiveTests(StaticAccessToInstanceMemberTest);
+    defineReflectiveTests(StaticAccessToInstanceMemberTest);
     defineReflectiveTests(StaticAccessToInstanceMemberWithExtensionMethodsTest);
   });
 }
 
 @reflectiveTest
-class StaticAccessToInstanceMemberTest extends DriverResolutionTest {}
+class StaticAccessToInstanceMemberTest extends DriverResolutionTest {
+  test_method_invocation() async {
+    await assertErrorsInCode('''
+class A {
+  m() {}
+}
+main() {
+  A.m();
+}''', [
+      error(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, 34, 1),
+    ]);
+  }
+
+  test_method_reference() async {
+    await assertErrorsInCode('''
+class A {
+  m() {}
+}
+main() {
+  A.m;
+}''', [
+      error(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, 34, 1),
+    ]);
+  }
+
+  test_propertyAccess_field() async {
+    await assertErrorsInCode('''
+class A {
+  var f;
+}
+main() {
+  A.f;
+}''', [
+      error(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, 34, 1),
+    ]);
+  }
+
+  test_propertyAccess_getter() async {
+    await assertErrorsInCode('''
+class A {
+  get f => 42;
+}
+main() {
+  A.f;
+}''', [
+      error(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, 40, 1),
+    ]);
+  }
+
+  test_propertyAccess_setter() async {
+    await assertErrorsInCode('''
+class A {
+  set f(x) {}
+}
+main() {
+  A.f = 42;
+}''', [
+      error(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, 39, 1),
+    ]);
+  }
+}
 
 @reflectiveTest
 class StaticAccessToInstanceMemberWithExtensionMethodsTest
diff --git a/pkg/analyzer/test/src/diagnostics/strict_raw_type_test.dart b/pkg/analyzer/test/src/diagnostics/strict_raw_type_test.dart
new file mode 100644
index 0000000..3a50c22
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/strict_raw_type_test.dart
@@ -0,0 +1,318 @@
+// 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/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.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(StrictRawTypeTest);
+    defineReflectiveTests(StrictRawType_WithExtensionsTest);
+  });
+}
+
+@reflectiveTest
+class StrictRawType_WithExtensionsTest extends DriverResolutionTest
+    with PackageMixin {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.extension_methods])
+    ..strictRawTypes = true;
+
+  test_typeOnExtendedType_anonymous_missing() async {
+    assertErrorsInCode(r'''
+extension on List {}
+''', [error(HintCode.STRICT_RAW_TYPE, 13, 4)]);
+  }
+
+  test_typeOnExtendedType_missing() async {
+    assertErrorsInCode(r'''
+extension E on List {}
+''', [error(HintCode.STRICT_RAW_TYPE, 15, 4)]);
+  }
+
+  test_typeOnExtendedType_optionalTypeArgs() async {
+    addMetaPackage();
+    assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+@optionalTypeArgs
+class C<T> {}
+extension E on C {}
+extension on C {}
+''');
+  }
+
+  test_typeOnExtendedType_present() async {
+    assertNoErrorsInCode(r'''
+extension E<T> on List<T> {}
+extension F on List<int> {}
+''');
+  }
+}
+
+@reflectiveTest
+class StrictRawTypeTest extends DriverResolutionTest with PackageMixin {
+  @override
+  AnalysisOptionsImpl get analysisOptions =>
+      AnalysisOptionsImpl()..strictRawTypes = true;
+
+  test_asExpression() async {
+    await assertNoErrorsInCode(r'''
+void f(dynamic x) {
+  print(x as List);
+  print(x as List<dynamic>);
+  print(x as List<List>);
+}
+''');
+  }
+
+  test_functionParts_optionalTypeArg() async {
+    addMetaPackage();
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+@optionalTypeArgs
+class C<T> {}
+C f(int a) => null;
+void g(C a) => print(a);
+''');
+  }
+
+  test_genericTypeArgument_missingTypeArg() async {
+    await assertErrorsInCode(r'''
+void f() {
+  var a = <List>[];
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
+      error(HintCode.STRICT_RAW_TYPE, 22, 4),
+    ]);
+  }
+
+  test_genericTypeArgument_withTypeArg() async {
+    await assertNoErrorsInCode(r'''
+void f() {
+  var a = <List<int>>[];
+}
+''');
+  }
+
+  test_isExpression() async {
+    await assertNoErrorsInCode(r'''
+void f(dynamic x) {
+  print(x is List);
+  print(x is List<dynamic>);
+  print(x is List<List>);
+}
+''');
+  }
+
+  test_localVariable_missingTypeArg() async {
+    await assertErrorsInCode(r'''
+void f() {
+  List a = [1, 2, 3];
+}
+''', [
+      error(HintCode.STRICT_RAW_TYPE, 13, 4),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 18, 1),
+    ]);
+  }
+
+  test_localVariable_withTypeArg() async {
+    await assertNoErrorsInCode(r'''
+void f() {
+  List<Object> a = [1, 2, 3];
+  print(a);
+}
+''');
+  }
+
+  test_mixinApplication_missing() async {
+    await assertErrorsInCode(r'''
+class C<T> {}
+class D = Object with C;
+''', [error(HintCode.STRICT_RAW_TYPE, 36, 1)]);
+  }
+
+  test_mixinApplication_withTypeArg() async {
+    await assertNoErrorsInCode(r'''
+class C<T> {}
+class D = Object with C<int>;
+''');
+  }
+
+  test_parameter_missingTypeArg() async {
+    await assertErrorsInCode(r'''
+void f(List a) {}
+''', [error(HintCode.STRICT_RAW_TYPE, 7, 4)]);
+  }
+
+  test_returnType_missingTypeArg() async {
+    await assertErrorsInCode(r'''
+List f(int a) => [1, 2, 3];
+''', [error(HintCode.STRICT_RAW_TYPE, 0, 4)]);
+  }
+
+  test_superclassWith_missingTypeArg() async {
+    await assertErrorsInCode(r'''
+class C<T> {}
+class D extends Object with C {}
+''', [error(HintCode.STRICT_RAW_TYPE, 42, 1)]);
+  }
+
+  test_superclassWith_withTypeArg() async {
+    await assertNoErrorsInCode(r'''
+class C<T> {}
+class D extends Object with C<int> {}
+''');
+  }
+
+  test_topLevelField_missingTypeArg() async {
+    await assertErrorsInCode(r'''
+List a;
+''', [error(HintCode.STRICT_RAW_TYPE, 0, 4)]);
+  }
+
+  test_topLevelField_optionalTypeArg() async {
+    addMetaPackage();
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+@optionalTypeArgs
+class C<T> {}
+C a;
+C get g => null;
+void set s(C a) {}
+''');
+  }
+
+  test_topLevelField_withTypeArg() async {
+    await assertNoErrorsInCode(r'''
+List<int> a;
+List<num> get g => [];
+void set s(List<double> a) {}
+''');
+  }
+
+  test_topLevelGetter_missingTypeArg() async {
+    await assertErrorsInCode(r'''
+List get g => [];
+''', [error(HintCode.STRICT_RAW_TYPE, 0, 4)]);
+  }
+
+  test_topLevelSetter_missingTypeArg() async {
+    await assertErrorsInCode(r'''
+void set s(List a) {}
+''', [error(HintCode.STRICT_RAW_TYPE, 11, 4)]);
+  }
+
+  test_typedef_classic_missingTypeArg() async {
+    await assertErrorsInCode(r'''
+typedef T F1<T>(T _);
+F1 func;
+''', [error(HintCode.STRICT_RAW_TYPE, 22, 2)]);
+  }
+
+  test_typedef_modern_missingTypeArg() async {
+    await assertErrorsInCode(r'''
+typedef F1<T> = T Function(T);
+F1 func;
+''', [error(HintCode.STRICT_RAW_TYPE, 31, 2)]);
+  }
+
+  test_typedef_modern_optionalTypeArgs() async {
+    addMetaPackage();
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+@optionalTypeArgs
+typedef T F1<T>(T _);
+@optionalTypeArgs
+typedef F2<T> = T Function(T);
+F1 f1;
+F2 f2;
+''');
+  }
+
+  test_typedef_modern_withTypeArg() async {
+    await assertNoErrorsInCode(r'''
+typedef T F1<T>(T _);
+typedef F2<T> = T Function(T);
+typedef F3 = T Function<T>(T);
+F1<int> f1;
+F2<int> f2;
+F3 f3;
+''');
+  }
+
+  test_TypeOnClassDeclaration_optionalTypeArgs() async {
+    addMetaPackage();
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+@optionalTypeArgs
+class C<T> {}
+class D extends C {}
+class E extends Object with C {}
+class F = Object with C;
+class G implements C {}
+''');
+  }
+
+  test_TypeOnConstructor() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  C();
+  C.named();
+}
+
+var c = C();
+var d = C.named();
+''');
+  }
+
+  test_TypeOnInterface_missing() async {
+    await assertErrorsInCode(r'''
+class C<T> {}
+class D implements C {}
+''', [error(HintCode.STRICT_RAW_TYPE, 33, 1)]);
+  }
+
+  test_TypeOnInterface_withTypeArg() async {
+    await assertNoErrorsInCode(r'''
+class C<T> {}
+class D implements C<int> {}
+''');
+  }
+
+  test_TypeOnSuperclass_missing() async {
+    await assertErrorsInCode(r'''
+class C<T> {}
+class D extends C {}
+''', [error(HintCode.STRICT_RAW_TYPE, 30, 1)]);
+  }
+
+  test_TypeOnSuperclass_withTypeArg() async {
+    await assertNoErrorsInCode(r'''
+class C<T> {}
+class D extends C<int> {}
+''');
+  }
+
+  test_typeParameterBound_missingTypeArg() async {
+    await assertErrorsInCode(r'''
+class C<T> {}
+class D<T extends C> {}
+''', [error(HintCode.STRICT_RAW_TYPE, 32, 1)]);
+  }
+
+  test_typeParameterBound_withTypeArg() async {
+    await assertNoErrorsInCode(r'''
+class C<T> {}
+class D<S, T extends C<S>> {}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/switch_expression_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/switch_expression_not_assignable_test.dart
new file mode 100644
index 0000000..e8d5051
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/switch_expression_not_assignable_test.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 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(SwitchExpressionNotAssignableTest);
+  });
+}
+
+@reflectiveTest
+class SwitchExpressionNotAssignableTest extends DriverResolutionTest {
+  test_simple() async {
+    await assertErrorsInCode('''
+f(int p) {
+  switch (p) {
+    case 'a': break;
+  }
+}''', [
+      error(StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE, 21, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index b953550..5dbd49a 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -79,6 +79,8 @@
     as extension_override_access_to_static_member;
 import 'extension_override_argument_not_assignable_test.dart'
     as extension_override_argument_not_assignable;
+import 'extension_override_with_cascade_test.dart'
+    as extension_override_with_cascade;
 import 'extension_override_without_access_test.dart'
     as extension_override_without_access;
 import 'extra_positional_arguments_test.dart' as extra_positional_arguments;
@@ -103,6 +105,10 @@
 import 'import_duplicated_library_named_test.dart'
     as import_duplicated_library_named;
 import 'import_of_non_library_test.dart' as import_of_non_library;
+import 'inference_failure_on_collection_literal_test.dart'
+    as inference_failure_on_collection_literal;
+import 'inference_failure_on_function_return_type_test.dart'
+    as inference_failure_on_function_return_type;
 import 'inference_failure_on_uninitialized_variable_test.dart'
     as inference_failure_on_uninitialized_variable;
 import 'inference_failure_on_untyped_parameter_test.dart'
@@ -263,23 +269,37 @@
     as spread_expression_from_deferred_library;
 import 'static_access_to_instance_member_test.dart'
     as static_access_to_instance_member;
+import 'strict_raw_type_test.dart' as strict_raw_type;
 import 'subtype_of_sealed_class_test.dart' as subtype_of_sealed_class;
 import 'super_in_extension_test.dart' as super_in_extension;
+import 'switch_expression_not_assignable_test.dart'
+    as switch_expression_not_assignable;
 import 'top_level_instance_getter_test.dart' as top_level_instance_getter;
 import 'top_level_instance_method_test.dart' as top_level_instance_method;
+import 'type_annotation_deferred_class_test.dart'
+    as type_annotation_deferred_class;
 import 'type_argument_not_matching_bounds_test.dart'
     as type_argument_not_matching_bounds;
 import 'type_check_is_not_null_test.dart' as type_check_is_not_null;
 import 'type_check_is_null_test.dart' as type_check_is_null;
+import 'type_parameter_referenced_by_static_test.dart'
+    as type_parameter_referenced_by_static;
+import 'type_test_with_non_type_test.dart' as type_test_with_non_type;
+import 'type_test_with_undefined_name_test.dart'
+    as type_test_with_undefined_name;
 import 'unchecked_use_of_nullable_value_test.dart'
     as unchecked_use_of_nullable_value;
+import 'undefined_class_boolean_test.dart' as undefined_class_boolean;
+import 'undefined_class_test.dart' as undefined_class;
 import 'undefined_extension_getter_test.dart' as undefined_extension_getter;
 import 'undefined_extension_method_test.dart' as undefined_extension_method;
 import 'undefined_extension_setter_test.dart' as undefined_extension_setter;
 import 'undefined_getter_test.dart' as undefined_getter;
 import 'undefined_hidden_name_test.dart' as undefined_hidden_name;
+import 'undefined_identifier_await_test.dart' as undefined_identifier_await;
 import 'undefined_identifier_test.dart' as undefined_identifier;
 import 'undefined_method_test.dart' as undefined_method;
+import 'undefined_named_parameter_test.dart' as undefined_named_parameter;
 import 'undefined_operator_test.dart' as undefined_operator;
 import 'undefined_prefixed_name_test.dart' as undefined_prefixed_name;
 import 'undefined_setter_test.dart' as undefined_setter;
@@ -293,6 +313,8 @@
     as unnecessary_null_aware_spread;
 import 'unnecessary_type_check_false_test.dart' as unnecessary_type_check_false;
 import 'unnecessary_type_check_true_test.dart' as unnecessary_type_check_true;
+import 'unqualified_reference_to_static_member_of_extended_type_test.dart'
+    as unqualified_reference_to_static_member_of_extended_type;
 import 'unused_catch_clause_test.dart' as unused_catch_clause;
 import 'unused_catch_stack_test.dart' as unused_catch_stack;
 import 'unused_element_test.dart' as unused_element;
@@ -362,6 +384,7 @@
     extension_declares_member_of_object.main();
     extension_override_access_to_static_member.main();
     extension_override_argument_not_assignable.main();
+    extension_override_with_cascade.main();
     extension_override_without_access.main();
     extra_positional_arguments.main();
     field_initialized_in_initializer_and_declaration.main();
@@ -376,6 +399,8 @@
     import_deferred_library_with_load_function.main();
     import_duplicated_library_named.main();
     import_of_non_library.main();
+    inference_failure_on_collection_literal.main();
+    inference_failure_on_function_return_type.main();
     inference_failure_on_uninitialized_variable.main();
     inference_failure_on_untyped_parameter.main();
     instance_access_to_static_member.main();
@@ -484,21 +509,31 @@
     set_element_type_not_assignable.main();
     spread_expression_from_deferred_library.main();
     static_access_to_instance_member.main();
+    strict_raw_type.main();
     subtype_of_sealed_class.main();
     super_in_extension.main();
+    switch_expression_not_assignable.main();
     top_level_instance_getter.main();
     top_level_instance_method.main();
+    type_annotation_deferred_class.main();
     type_argument_not_matching_bounds.main();
     type_check_is_not_null.main();
     type_check_is_null.main();
+    type_parameter_referenced_by_static.main();
+    type_test_with_non_type.main();
+    type_test_with_undefined_name.main();
     unchecked_use_of_nullable_value.main();
+    undefined_class_boolean.main();
+    undefined_class.main();
     undefined_extension_getter.main();
     undefined_extension_method.main();
     undefined_extension_setter.main();
     undefined_getter.main();
     undefined_hidden_name.main();
+    undefined_identifier_await.main();
     undefined_identifier.main();
     undefined_method.main();
+    undefined_named_parameter.main();
     undefined_operator.main();
     undefined_prefixed_name.main();
     undefined_setter.main();
@@ -510,6 +545,7 @@
     unnecessary_null_aware_spread.main();
     unnecessary_type_check_false.main();
     unnecessary_type_check_true.main();
+    unqualified_reference_to_static_member_of_extended_type.main();
     unused_catch_clause.main();
     unused_catch_stack.main();
     unused_element.main();
diff --git a/pkg/analyzer/test/src/diagnostics/type_annotation_deferred_class_test.dart b/pkg/analyzer/test/src/diagnostics/type_annotation_deferred_class_test.dart
new file mode 100644
index 0000000..516f8c5
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/type_annotation_deferred_class_test.dart
@@ -0,0 +1,178 @@
+// 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(TypeAnnotationDeferredClassTest);
+  });
+}
+
+@reflectiveTest
+class TypeAnnotationDeferredClassTest extends DriverResolutionTest {
+  test_asExpression() async {
+    newFile("/test/lib/lib1.dart", content: '''
+library lib1;
+class A {}''');
+    await assertErrorsInCode('''
+library root;
+import 'lib1.dart' deferred as a;
+f(var v) {
+  v as a.A;
+}''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 66, 3),
+    ]);
+  }
+
+  test_catchClause() async {
+    newFile("/test/lib/lib1.dart", content: '''
+library lib1;
+class A {}''');
+    await assertErrorsInCode('''
+library root;
+import 'lib1.dart' deferred as a;
+f(var v) {
+  try {
+  } on a.A {
+  }
+}''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 74, 3),
+    ]);
+  }
+
+  test_fieldFormalParameter() async {
+    newFile("/test/lib/lib1.dart", content: '''
+library lib1;
+class A {}''');
+    await assertErrorsInCode('''
+library root;
+import 'lib1.dart' deferred as a;
+class C {
+  var v;
+  C(a.A this.v);
+}''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 71, 3),
+    ]);
+  }
+
+  test_functionDeclaration_returnType() async {
+    newFile("/test/lib/lib1.dart", content: '''
+library lib1;
+class A {}''');
+    await assertErrorsInCode('''
+library root;
+import 'lib1.dart' deferred as a;
+a.A f() { return null; }''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 48, 3),
+    ]);
+  }
+
+  test_functionTypedFormalParameter_returnType() async {
+    newFile("/test/lib/lib1.dart", content: '''
+library lib1;
+class A {}''');
+    await assertErrorsInCode('''
+library root;
+import 'lib1.dart' deferred as a;
+f(a.A g()) {}''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 50, 3),
+    ]);
+  }
+
+  test_isExpression() async {
+    newFile("/test/lib/lib1.dart", content: '''
+library lib1;
+class A {}''');
+    await assertErrorsInCode('''
+library root;
+import 'lib1.dart' deferred as a;
+f(var v) {
+  bool b = v is a.A;
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 66, 1),
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 75, 3),
+    ]);
+  }
+
+  test_methodDeclaration_returnType() async {
+    newFile("/test/lib/lib1.dart", content: '''
+library lib1;
+class A {}''');
+    await assertErrorsInCode('''
+library root;
+import 'lib1.dart' deferred as a;
+class C {
+  a.A m() { return null; }
+}''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 60, 3),
+    ]);
+  }
+
+  test_simpleFormalParameter() async {
+    newFile("/test/lib/lib1.dart", content: '''
+library lib1;
+class A {}''');
+    await assertErrorsInCode('''
+library root;
+import 'lib1.dart' deferred as a;
+f(a.A v) {}''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 50, 3),
+    ]);
+  }
+
+  test_typeArgumentList() async {
+    newFile("/test/lib/lib1.dart", content: '''
+library lib1;
+class A {}''');
+    await assertErrorsInCode('''
+library root;
+import 'lib1.dart' deferred as a;
+class C<E> {}
+C<a.A> c;''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 64, 3),
+    ]);
+  }
+
+  test_typeArgumentList2() async {
+    newFile("/test/lib/lib1.dart", content: '''
+library lib1;
+class A {}''');
+    await assertErrorsInCode('''
+library root;
+import 'lib1.dart' deferred as a;
+class C<E, F> {}
+C<a.A, a.A> c;''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 67, 3),
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 72, 3),
+    ]);
+  }
+
+  test_typeParameter_bound() async {
+    newFile("/test/lib/lib1.dart", content: '''
+library lib1;
+class A {}''');
+    await assertErrorsInCode('''
+library root;
+import 'lib1.dart' deferred as a;
+class C<E extends a.A> {}''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 66, 3),
+    ]);
+  }
+
+  test_variableDeclarationList() async {
+    newFile("/test/lib/lib1.dart", content: '''
+library lib1;
+class A {}''');
+    await assertErrorsInCode('''
+library root;
+import 'lib1.dart' deferred as a;
+a.A v;''', [
+      error(StaticWarningCode.TYPE_ANNOTATION_DEFERRED_CLASS, 48, 3),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/type_parameter_referenced_by_static_test.dart b/pkg/analyzer/test/src/diagnostics/type_parameter_referenced_by_static_test.dart
new file mode 100644
index 0000000..2b54d51
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/type_parameter_referenced_by_static_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.
+
+import 'package:analyzer/src/dart/error/hint_codes.dart';
+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(TypeParameterReferencedByStaticTest);
+  });
+}
+
+@reflectiveTest
+class TypeParameterReferencedByStaticTest extends DriverResolutionTest {
+  test_field() async {
+    await assertErrorsInCode('''
+class A<K> {
+  static K k;
+}''', [
+      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 22, 1),
+    ]);
+  }
+
+  test_getter() async {
+    await assertErrorsInCode('''
+class A<K> {
+  static K get k => null;
+}''', [
+      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 22, 1),
+    ]);
+  }
+
+  test_methodBodyReference() async {
+    await assertErrorsInCode('''
+class A<K> {
+  static m() {
+    K k;
+  }
+}''', [
+      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 32, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 34, 1),
+    ]);
+  }
+
+  test_methodParameter() async {
+    await assertErrorsInCode('''
+class A<K> {
+  static m(K k) {}
+}''', [
+      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 24, 1),
+    ]);
+  }
+
+  test_methodReturn() async {
+    await assertErrorsInCode('''
+class A<K> {
+  static K m() { return null; }
+}''', [
+      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 22, 1),
+    ]);
+  }
+
+  test_setter() async {
+    await assertErrorsInCode('''
+class A<K> {
+  static set s(K k) {}
+}''', [
+      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 28, 1),
+    ]);
+  }
+
+  test_simpleIdentifier() async {
+    await assertErrorsInCode('''
+class A<T> {
+  static foo() {
+    T;
+  }
+}
+''', [
+      error(StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC, 34, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/type_test_with_non_type_test.dart b/pkg/analyzer/test/src/diagnostics/type_test_with_non_type_test.dart
new file mode 100644
index 0000000..39f086c9
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/type_test_with_non_type_test.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 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(TypeTestWithNonTypeTest);
+  });
+}
+
+@reflectiveTest
+class TypeTestWithNonTypeTest extends DriverResolutionTest {
+  test_parameter() async {
+    await assertErrorsInCode('''
+var A = 0;
+f(var p) {
+  if (p is A) {
+  }
+}''', [
+      error(StaticWarningCode.TYPE_TEST_WITH_NON_TYPE, 33, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/type_test_with_undefined_name_test.dart b/pkg/analyzer/test/src/diagnostics/type_test_with_undefined_name_test.dart
new file mode 100644
index 0000000..b530cf4
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/type_test_with_undefined_name_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.
+
+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(TypeTestWithUndefinedNameTest);
+  });
+}
+
+@reflectiveTest
+class TypeTestWithUndefinedNameTest extends DriverResolutionTest {
+  test_undefined() async {
+    await assertErrorsInCode('''
+f(var p) {
+  if (p is A) {
+  }
+}''', [
+      error(StaticWarningCode.TYPE_TEST_WITH_UNDEFINED_NAME, 22, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_class_boolean_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_class_boolean_test.dart
new file mode 100644
index 0000000..8ee9e4b
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/undefined_class_boolean_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.
+
+import 'package:analyzer/src/dart/error/hint_codes.dart';
+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(UndefinedClassBooleanTest);
+  });
+}
+
+@reflectiveTest
+class UndefinedClassBooleanTest extends DriverResolutionTest {
+  test_variableDeclaration() async {
+    await assertErrorsInCode('''
+f() { boolean v; }
+''', [
+      error(StaticWarningCode.UNDEFINED_CLASS_BOOLEAN, 6, 7),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_class_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_class_test.dart
new file mode 100644
index 0000000..3c8a91c
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/undefined_class_test.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:analyzer/src/dart/error/hint_codes.dart';
+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(UndefinedClassTest);
+  });
+}
+
+@reflectiveTest
+class UndefinedClassTest extends DriverResolutionTest {
+  test_instanceCreation() async {
+    await assertErrorsInCode('''
+f() { new C(); }
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_CLASS, 10, 1),
+    ]);
+  }
+
+  test_variableDeclaration() async {
+    await assertErrorsInCode('''
+f() { C c; }
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_CLASS, 6, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 8, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_extension_getter_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_extension_getter_test.dart
index 1917d08..1eb33a7 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_extension_getter_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_extension_getter_test.dart
@@ -46,14 +46,27 @@
 
   test_override_undefined_hasSetter() async {
     await assertErrorsInCode('''
-extension E on String {
-  void set s(int x) {}
+extension E on int {
+  set foo(int _) {}
 }
 f() {
-  E('a').s += 1;
+  E(0).foo;
 }
 ''', [
-      error(CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER, 64, 1),
+      error(CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER, 56, 3),
+    ]);
+  }
+
+  test_override_undefined_hasSetter_plusEq() async {
+    await assertErrorsInCode('''
+extension E on int {
+  set foo(int _) {}
+}
+f() {
+  E(0).foo += 1;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER, 56, 3),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_extension_setter_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_extension_setter_test.dart
index f6c2f65..4dffd2a 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_extension_setter_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_extension_setter_test.dart
@@ -44,7 +44,7 @@
     ]);
   }
 
-  test_override_undefined_hasGetter() async {
+  test_override_undefined_hasGetter_eq() async {
     await assertErrorsInCode('''
 extension E on int {
   int get foo => 0;
@@ -57,6 +57,19 @@
     ]);
   }
 
+  test_override_undefined_hasGetter_plusEq() async {
+    await assertErrorsInCode('''
+extension E on int {
+  int get foo => 0;
+}
+f() {
+  E(0).foo += 1;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER, 56, 3),
+    ]);
+  }
+
   test_static_undefined() async {
     await assertErrorsInCode('''
 extension E on int {}
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart
index 5f3050e..92f90de 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart
@@ -18,6 +18,34 @@
 
 @reflectiveTest
 class UndefinedGetterTest extends DriverResolutionTest {
+  test_compoundAssignment_hasSetter_instance() async {
+    await assertErrorsInCode('''
+class C {
+  set foo(int _) {}
+}
+
+f(C c) {
+  c.foo += 1;
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 46, 3),
+    ]);
+  }
+
+  test_compoundAssignment_hasSetter_static() async {
+    await assertErrorsInCode('''
+class C {
+  static set foo(int _) {}
+}
+
+f() {
+  C.foo += 1;
+}
+''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 50, 3),
+    ]);
+  }
+
   test_ifElement_inList_notPromoted() async {
     await assertErrorsInCode('''
 f(int x) {
@@ -116,6 +144,29 @@
       error(StaticTypeWarningCode.UNDEFINED_GETTER, 66, 6),
     ]);
   }
+
+  test_static_definedInSuperclass() async {
+    await assertErrorsInCode('''
+class S {
+  static int get g => 0;
+}
+class C extends S {}
+f(var p) {
+  f(C.g);
+}''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 75, 1),
+    ]);
+  }
+
+  test_static_undefined() async {
+    await assertErrorsInCode('''
+class C {}
+f(var p) {
+  f(C.m);
+}''', [
+      error(StaticTypeWarningCode.UNDEFINED_GETTER, 28, 1),
+    ]);
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_identifier_await_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_identifier_await_test.dart
new file mode 100644
index 0000000..89019f9
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/undefined_identifier_await_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.
+
+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(UndefinedIdentifierAwaitTest);
+  });
+}
+
+@reflectiveTest
+class UndefinedIdentifierAwaitTest extends DriverResolutionTest {
+  test_function() async {
+    await assertErrorsInCode('''
+void a() { await; }
+''', [
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT, 11, 5),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart
index 895322a..64d01e9 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart
@@ -15,6 +15,27 @@
 
 @reflectiveTest
 class UndefinedIdentifierTest extends DriverResolutionTest {
+  @failingTest
+  test_commentReference() async {
+    await assertErrorsInCode('''
+/** [m] xxx [new B.c] */
+class A {
+}''', [
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 5, 1),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 17, 1),
+    ]);
+  }
+
+  test_for() async {
+    await assertErrorsInCode('''
+f(var l) {
+  for (e in l) {
+  }
+}''', [
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 18, 1),
+    ]);
+  }
+
   test_forElement_inList_insideElement() async {
     await assertNoErrorsInCode('''
 f(Object x) {
@@ -55,4 +76,74 @@
       error(StaticWarningCode.UNDEFINED_IDENTIFIER, 31, 1),
     ]);
   }
+
+  test_function() async {
+    await assertErrorsInCode('''
+int a() => b;
+''', [
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 11, 1),
+    ]);
+  }
+
+  test_importCore_withShow() async {
+    await assertErrorsInCode('''
+import 'dart:core' show List;
+main() {
+  List;
+  String;
+}''', [
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 49, 6),
+    ]);
+  }
+
+  test_initializer() async {
+    await assertErrorsInCode('''
+var a = b;
+''', [
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 8, 1),
+    ]);
+  }
+
+  test_methodInvocation() async {
+    await assertErrorsInCode('''
+f() { C.m(); }
+''', [
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 6, 1),
+    ]);
+  }
+
+  test_private_getter() async {
+    newFile("/test/lib/lib.dart", content: '''
+library lib;
+class A {
+  var _foo;
+}''');
+    await assertErrorsInCode('''
+import 'lib.dart';
+class B extends A {
+  test() {
+    var v = _foo;
+  }
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 58, 1),
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 62, 4),
+    ]);
+  }
+
+  test_private_setter() async {
+    newFile("/test/lib/lib.dart", content: '''
+library lib;
+class A {
+  var _foo;
+}''');
+    await assertErrorsInCode('''
+import 'lib.dart';
+class B extends A {
+  test() {
+    _foo = 42;
+  }
+}''', [
+      error(StaticWarningCode.UNDEFINED_IDENTIFIER, 54, 4),
+    ]);
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_named_parameter_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_named_parameter_test.dart
new file mode 100644
index 0000000..4381a76
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/undefined_named_parameter_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.
+
+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(UndefinedNamedParameterTest);
+  });
+}
+
+@reflectiveTest
+class UndefinedNamedParameterTest extends DriverResolutionTest {
+  test_undefined() async {
+    await assertErrorsInCode('''
+f({a, b}) {}
+main() {
+  f(c: 1);
+}''', [
+      error(CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER, 26, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_setter_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_setter_test.dart
index 9340c2e..f1d7322 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_setter_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_setter_test.dart
@@ -47,6 +47,19 @@
       error(StaticTypeWarningCode.UNDEFINED_SETTER, 43, 1),
     ]);
   }
+
+  test_static_definedInSuperclass() async {
+    await assertErrorsInCode('''
+class S {
+  static set s(int i) {}
+}
+class C extends S {}
+f(var p) {
+  f(C.s = 1);
+}''', [
+      error(StaticTypeWarningCode.UNDEFINED_SETTER, 75, 1),
+    ]);
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/diagnostics/unqualified_reference_to_static_member_of_extended_type_test.dart b/pkg/analyzer/test/src/diagnostics/unqualified_reference_to_static_member_of_extended_type_test.dart
new file mode 100644
index 0000000..d8cd1da
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/unqualified_reference_to_static_member_of_extended_type_test.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.
+
+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';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UnqualifiedReferenceToStaticMemberOfExtendedTypeTest);
+  });
+}
+
+@reflectiveTest
+class UnqualifiedReferenceToStaticMemberOfExtendedTypeTest
+    extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.extension_methods]);
+
+  test_getter() async {
+    await assertErrorsInCode('''
+class MyClass {
+  static int get zero => 0;
+}
+extension MyExtension on MyClass {
+  void m() {
+    zero;
+  }
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE,
+          98,
+          4),
+    ]);
+  }
+
+  test_method() async {
+    await assertErrorsInCode('''
+class MyClass {
+  static void sm() {}
+}
+extension MyExtension on MyClass {
+  void m() {
+    sm();
+  }
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE,
+          92,
+          2),
+    ]);
+  }
+
+  test_setter() async {
+    await assertErrorsInCode('''
+class MyClass {
+  static set foo(int i) {}
+}
+extension MyExtension on MyClass {
+  void m() {
+    foo = 3;
+  }
+}
+''', [
+      error(
+          CompileTimeErrorCode
+              .UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE,
+          97,
+          3),
+    ]);
+  }
+}
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 322c773..52917c9 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
@@ -43,6 +43,34 @@
     ]);
   }
 
+  test_assignmentExpression_function() async {
+    await assertErrorsInCode('''
+void f() {}
+class A {
+  n() {
+    var a;
+    a = f();
+  }
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 38, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 49, 1),
+    ]);
+  }
+
+  test_assignmentExpression_method() async {
+    await assertErrorsInCode('''
+class A {
+  void m() {}
+  n() {
+    var a;
+    a = m();
+  }
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 40, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 51, 1),
+    ]);
+  }
+
   test_assignmentToVoidParameterOk() async {
     // Note: the spec may decide to disallow this, but at this point that seems
     // highly unlikely.
@@ -66,6 +94,14 @@
 ''');
   }
 
+  test_await() async {
+    await assertNoErrorsInCode('''
+main() async {
+  void x;
+  await x;
+}''');
+  }
+
   test_implicitReturnValue() async {
     await assertNoErrorsInCode(r'''
 f() {}
@@ -77,6 +113,29 @@
 ''');
   }
 
+  test_inForLoop_error() async {
+    await assertErrorsInCode('''
+class A {
+  void m() {}
+  n() {
+    for(Object a = m();;) {}
+  }
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 47, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 51, 1),
+    ]);
+  }
+
+  test_inForLoop_ok() async {
+    await assertNoErrorsInCode('''
+class A {
+  void m() {}
+  n() {
+    for(void a = m();;) {}
+  }
+}''');
+  }
+
   test_interpolateVoidValueError() async {
     await assertErrorsInCode(r'''
 void main() {
@@ -504,6 +563,67 @@
 ''');
   }
 
+  test_variableDeclaration_function_error() async {
+    await assertErrorsInCode('''
+void f() {}
+class A {
+  n() {
+    Object a = f();
+  }
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 41, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 45, 1),
+    ]);
+  }
+
+  test_variableDeclaration_function_ok() async {
+    await assertNoErrorsInCode('''
+void f() {}
+class A {
+  n() {
+    void a = f();
+  }
+}''');
+  }
+
+  test_variableDeclaration_method2() async {
+    await assertErrorsInCode('''
+class A {
+  void m() {}
+  n() {
+    Object a = m(), b = m();
+  }
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 43, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 47, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 52, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 56, 1),
+    ]);
+  }
+
+  test_variableDeclaration_method_error() async {
+    await assertErrorsInCode('''
+class A {
+  void m() {}
+  n() {
+    Object a = m();
+  }
+}''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 43, 1),
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 47, 1),
+    ]);
+  }
+
+  test_variableDeclaration_method_ok() async {
+    await assertNoErrorsInCode('''
+class A {
+  void m() {}
+  n() {
+    void a = m();
+  }
+}''');
+  }
+
   test_yieldStarVoid_asyncStar() async {
     await assertErrorsInCode('''
 main(void x) async* {
diff --git a/pkg/analyzer/test/src/source/source_resource_test.dart b/pkg/analyzer/test/src/source/source_resource_test.dart
index 863117b..81dbccc 100644
--- a/pkg/analyzer/test/src/source/source_resource_test.dart
+++ b/pkg/analyzer/test/src/source/source_resource_test.dart
@@ -4,7 +4,6 @@
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/java_engine_io.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -86,14 +85,6 @@
     FileSource.fileReadMode = (String s) => s;
   }
 
-  void test_getEncoding() {
-    SourceFactory factory =
-        new SourceFactory([new ResourceUriResolver(resourceProvider)]);
-    File file = getFile("/does/not/exist.dart");
-    FileSource source = new FileSource(file);
-    expect(factory.fromEncoding(source.encoding), source);
-  }
-
   void test_getFullName() {
     File file = getFile("/does/not/exist.dart");
     FileSource source = new FileSource(file);
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index d810032..d0ffbb9 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -7,6 +7,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/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';
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index e68375d..d3e4e8a 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.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/file_system/file_system.dart';
 import 'package:analyzer/src/context/context.dart';
diff --git a/pkg/analyzer/test/src/summary/top_level_inference_test.dart b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
index 72e6c9f..f738485 100644
--- a/pkg/analyzer/test/src/summary/top_level_inference_test.dart
+++ b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
@@ -333,7 +333,7 @@
   String aaa;
 }
 class C implements A, B {
-  /*error:INVALID_OVERRIDE,error:INVALID_OVERRIDE*/var aaa;
+  var /*error:INVALID_OVERRIDE,error:INVALID_OVERRIDE*/aaa;
 }
 ''';
     await checkFile(content);
diff --git a/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart b/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart
index 906407f..a20b7da 100644
--- a/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart
+++ b/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/summary2/ast_text_printer.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -11,6 +13,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AstTextPrinterTest);
+    defineReflectiveTests(AstTextPrinterWithExtensionMethodsTest);
   });
 }
 
@@ -109,3 +112,21 @@
 ''');
   }
 }
+
+@reflectiveTest
+class AstTextPrinterWithExtensionMethodsTest extends ParseBase {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.extension_methods]);
+
+  test_extensionOverride() async {
+    await assertParseCodeAndPrintAst(this, '''
+extension E on Object {
+  int f() => 0;
+}
+
+const e = E(null).f();
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 7360730..6948841 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -538,16 +538,16 @@
 class G extends E implements D {}
 
 class D_error extends C {
-  /*error:INVALID_OVERRIDE*/int f(int x) => x;
+  int /*error:INVALID_OVERRIDE*/f(int x) => x;
 }
 class E_error extends D {
-  /*error:INVALID_OVERRIDE*/int f(covariant double x) => 0;
+  int /*error:INVALID_OVERRIDE*/f(covariant double x) => 0;
 }
 class F_error extends E {
-  /*error:INVALID_OVERRIDE*/int f(covariant double x) => 0;
+  int /*error:INVALID_OVERRIDE*/f(covariant double x) => 0;
 }
 class G_error extends E implements D {
-  /*error:INVALID_OVERRIDE*/int f(covariant double x) => 0;
+  int /*error:INVALID_OVERRIDE*/f(covariant double x) => 0;
 }
     ''');
   }
@@ -615,16 +615,16 @@
 class G extends E implements D {}
 
 class D_error extends C {
-  /*error:INVALID_OVERRIDE*/int f(String x) => 0;
+  int /*error:INVALID_OVERRIDE*/f(String x) => 0;
 }
 class E_error extends D {
-  /*error:INVALID_OVERRIDE*/int f(double x) => 0;
+  int /*error:INVALID_OVERRIDE*/f(double x) => 0;
 }
 class F_error extends E {
-  /*error:INVALID_OVERRIDE*/int f(double x) => 0;
+  int /*error:INVALID_OVERRIDE*/f(double x) => 0;
 }
 class G_error extends E implements D {
-  /*error:INVALID_OVERRIDE*/int f(double x) => 0;
+  int /*error:INVALID_OVERRIDE*/f(double x) => 0;
 }
     ''');
   }
@@ -717,17 +717,17 @@
 }
 
 class Child extends Base {
-  /*error:INVALID_OVERRIDE*/A f1; // invalid for getter
-  /*error:INVALID_OVERRIDE*/C f2; // invalid for setter
+  A /*error:INVALID_OVERRIDE*/f1; // invalid for getter
+  C /*error:INVALID_OVERRIDE*/f2; // invalid for setter
   var f3;
-  /*error:INVALID_OVERRIDE*/dynamic f4;
+  dynamic /*error:INVALID_OVERRIDE*/f4;
 }
 
 class Child2 implements Base {
-  /*error:INVALID_OVERRIDE*/A f1; // invalid for getter
-  /*error:INVALID_OVERRIDE*/C f2; // invalid for setter
+  A /*error:INVALID_OVERRIDE*/f1; // invalid for getter
+  C /*error:INVALID_OVERRIDE*/f2; // invalid for setter
   var f3;
-  /*error:INVALID_OVERRIDE*/dynamic f4;
+  dynamic /*error:INVALID_OVERRIDE*/f4;
 }
 ''');
   }
@@ -746,17 +746,17 @@
 }
 
 class Child extends Base {
-  /*error:INVALID_OVERRIDE*/A get f1 => null;
+  A get /*error:INVALID_OVERRIDE*/f1 => null;
   C get f2 => null;
   get f3 => null;
-  /*error:INVALID_OVERRIDE*/dynamic get f4 => null;
+  dynamic get /*error:INVALID_OVERRIDE*/f4 => null;
 }
 
 class /*error:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR*/Child2 implements Base {
-  /*error:INVALID_OVERRIDE*/A get f1 => null;
+  A get /*error:INVALID_OVERRIDE*/f1 => null;
   C get f2 => null;
   get f3 => null;
-  /*error:INVALID_OVERRIDE*/dynamic get f4 => null;
+  dynamic get /*error:INVALID_OVERRIDE*/f4 => null;
 }
 ''');
   }
@@ -770,12 +770,12 @@
 }
 
 class G extends F {
-  /*error:INVALID_OVERRIDE*/final ToVoid<int> f = null;
+  final ToVoid<int> /*error:INVALID_OVERRIDE*/f = null;
   final ToVoid<dynamic> g = null;
 }
 
 class H implements F {
-  /*error:INVALID_OVERRIDE*/final ToVoid<int> f = null;
+  final ToVoid<int> /*error:INVALID_OVERRIDE*/f = null;
   final ToVoid<dynamic> g = null;
 }
  ''');
@@ -833,7 +833,7 @@
   B get f5 => null;
 
   void set f1(A value) {}
-  /*error:INVALID_OVERRIDE*/void set f2(C value) {}
+  void set /*error:INVALID_OVERRIDE*/f2(C value) {}
   void set f3(value) {}
   void set f4(dynamic value) {}
   set f5(B value) {}
@@ -847,7 +847,7 @@
   B get f5 => null;
 
   void set f1(A value) {}
-  /*error:INVALID_OVERRIDE*/void set f2(C value) {}
+  void set /*error:INVALID_OVERRIDE*/f2(C value) {}
   void set f3(value) {}
   void set f4(dynamic value) {}
   set f5(B value) {}
@@ -1953,7 +1953,7 @@
 }
 
 class Derived<S extends A> extends Base<B> {
-  /*error:INVALID_OVERRIDE*/S foo() => null;
+  S /*error:INVALID_OVERRIDE*/foo() => null;
 }
 
 class Derived2<S extends B> extends Base<B> {
@@ -2061,10 +2061,10 @@
 }
 
 class Child extends Base {
-  /*error:INVALID_OVERRIDE*/A get f1 => null;
+  A get /*error:INVALID_OVERRIDE*/f1 => null;
   C get f2 => null;
   get f3 => null;
-  /*error:INVALID_OVERRIDE*/dynamic get f4 => null;
+  dynamic get /*error:INVALID_OVERRIDE*/f4 => null;
 }
 ''');
   }
@@ -2079,12 +2079,12 @@
 }
 
 class G extends F {
-  /*error:INVALID_OVERRIDE*/ToVoid<int> get f => null;
+  ToVoid<int> get /*error:INVALID_OVERRIDE*/f => null;
   ToVoid<dynamic> get g => null;
 }
 
 class H implements F {
-  /*error:INVALID_OVERRIDE*/ToVoid<int> get f => null;
+  ToVoid<int> get /*error:INVALID_OVERRIDE*/f => null;
   ToVoid<dynamic> get g => null;
 }
 ''');
@@ -2495,7 +2495,7 @@
   set x(Object y) {}
 }
 class D implements B, C {
-  /*error:INVALID_OVERRIDE*/int x;
+  int /*error:INVALID_OVERRIDE*/x;
 }
     ''');
   }
@@ -2509,13 +2509,13 @@
 abstract class M implements I {}
 
 class C extends Object with M {
-  /*error:INVALID_OVERRIDE*/String x;
+  String /*error:INVALID_OVERRIDE*/x;
 }
 
 abstract class M2 = Object with M;
 
 class C2 extends Object with M2 {
-  /*error:INVALID_OVERRIDE*/String x;
+  String /*error:INVALID_OVERRIDE*/x;
 }
     ''');
   }
@@ -2545,13 +2545,13 @@
 abstract class M<E> implements I<E> {}
 
 class C extends Object with M<int> {
-  /*error:INVALID_OVERRIDE*/String x;
+  String /*error:INVALID_OVERRIDE*/x;
 }
 
 abstract class D extends Object with M<num> {}
 /*error:CONFLICTING_GENERIC_INTERFACES*/
 /*error:CONFLICTING_GENERIC_INTERFACES*/class E extends D with M<int> {
-  /*error:INVALID_OVERRIDE*/int x;
+  int /*error:INVALID_OVERRIDE*/x;
 }
 /*error:CONFLICTING_GENERIC_INTERFACES*/
 /*error:CONFLICTING_GENERIC_INTERFACES*/class F extends D with M<int> {
@@ -2588,37 +2588,37 @@
 }
 
 class T1 extends Base {
-  /*error:INVALID_OVERRIDE*/B get /*error:MISMATCHED_GETTER_AND_SETTER_TYPES*/f => null;
+  B get /*error:INVALID_OVERRIDE, error:MISMATCHED_GETTER_AND_SETTER_TYPES*/f => null;
 }
 
 class T2 extends Base {
-  /*error:INVALID_OVERRIDE*/set /*error:MISMATCHED_GETTER_AND_SETTER_TYPES*/f(
+  set /*error:INVALID_OVERRIDE, error:MISMATCHED_GETTER_AND_SETTER_TYPES*/f(
       B b) => null;
 }
 
 class T3 extends Base {
-  /*error:INVALID_OVERRIDE*/final B
-      /*error:FINAL_NOT_INITIALIZED, error:MISMATCHED_GETTER_AND_SETTER_TYPES*/f;
+  final B
+      /*error:FINAL_NOT_INITIALIZED, error:INVALID_OVERRIDE, error:MISMATCHED_GETTER_AND_SETTER_TYPES*/f;
 }
 class T4 extends Base {
   // two: one for the getter one for the setter.
-  /*error:INVALID_OVERRIDE, error:INVALID_OVERRIDE*/B f;
+  B /*error:INVALID_OVERRIDE, error:INVALID_OVERRIDE*/f;
 }
 
 class /*error:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE*/T5 implements Base {
-  /*error:INVALID_OVERRIDE*/B get /*error:MISMATCHED_GETTER_AND_SETTER_TYPES*/f => null;
+  /**/B get /*error:INVALID_OVERRIDE, error:MISMATCHED_GETTER_AND_SETTER_TYPES*/f => null;
 }
 
 class /*error:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE*/T6 implements Base {
-  /*error:INVALID_OVERRIDE*/set /*error:MISMATCHED_GETTER_AND_SETTER_TYPES*/f(B b) => null;
+  set /*error:INVALID_OVERRIDE, error:MISMATCHED_GETTER_AND_SETTER_TYPES*/f(B b) => null;
 }
 
 class /*error:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE*/T7 implements Base {
-  /*error:INVALID_OVERRIDE*/final B /*error:MISMATCHED_GETTER_AND_SETTER_TYPES*/f = null;
+  final B /*error:INVALID_OVERRIDE, error:MISMATCHED_GETTER_AND_SETTER_TYPES*/f = null;
 }
 class T8 implements Base {
   // two: one for the getter one for the setter.
-  /*error:INVALID_OVERRIDE, error:INVALID_OVERRIDE*/B f;
+  B /*error:INVALID_OVERRIDE, error:INVALID_OVERRIDE*/f;
 }
 ''');
   }
@@ -3339,12 +3339,12 @@
 }
 
 class Child extends Base {
-  /*error:INVALID_OVERRIDE*/A m1(A value) => null;
-  /*error:INVALID_OVERRIDE*/C m2(C value) => null;
-  /*error:INVALID_OVERRIDE*/A m3(C value) => null;
+  A /*error:INVALID_OVERRIDE*/m1(A value) => null;
+  C /*error:INVALID_OVERRIDE*/m2(C value) => null;
+  A /*error:INVALID_OVERRIDE*/m3(C value) => null;
   C m4(A value) => null;
   m5(value) => null;
-  /*error:INVALID_OVERRIDE*/dynamic m6(dynamic value) => null;
+  dynamic /*error:INVALID_OVERRIDE*/m6(dynamic value) => null;
 }
 ''');
   }
@@ -3363,12 +3363,12 @@
 }
 
 class G extends F {
-  /*error:INVALID_OVERRIDE*/void f(int x) {}
+  void /*error:INVALID_OVERRIDE*/f(int x) {}
   void g(dynamic x) {}
 }
 
 class H implements F {
-  /*error:INVALID_OVERRIDE*/void f(int x) {}
+  void /*error:INVALID_OVERRIDE*/f(int x) {}
   void g(dynamic x) {}
 }
 ''');
@@ -3749,7 +3749,7 @@
     return checkFile(r'''
 abstract class A { void test(A arg) { } }
 abstract class B extends A {
-  /*error:INVALID_OVERRIDE*/void test(B arg) { }
+  void /*error:INVALID_OVERRIDE*/test(B arg) { }
 }
 abstract class X implements A { }
 
@@ -3779,7 +3779,7 @@
   var _f3;
   var _f4;
 
-  /*error:INVALID_OVERRIDE*/String _m1() => null;
+  String /*error:INVALID_OVERRIDE*/_m1() => null;
 }
 ''', name: '/helper.dart');
     await checkFile('''
@@ -4063,15 +4063,15 @@
 
 class G extends F {
   void set f(ToVoid<int> x) {}
-  /*error:INVALID_OVERRIDE*/void set g(ToVoid<dynamic> x) {}
-  /*error:INVALID_OVERRIDE*/void set h(int x) {}
+  void set /*error:INVALID_OVERRIDE*/g(ToVoid<dynamic> x) {}
+  void set /*error:INVALID_OVERRIDE*/h(int x) {}
   void set i(dynamic x) {}
 }
 
 class H implements F {
   void set f(ToVoid<int> x) {}
-  /*error:INVALID_OVERRIDE*/void set g(ToVoid<dynamic> x) {}
-  /*error:INVALID_OVERRIDE*/void set h(int x) {}
+  void set /*error:INVALID_OVERRIDE*/g(ToVoid<dynamic> x) {}
+  void set /*error:INVALID_OVERRIDE*/h(int x) {}
   void set i(dynamic x) {}
 }
  ''');
@@ -4111,7 +4111,7 @@
 
 class Child extends Base {
   void set f1(A value) {}
-  /*error:INVALID_OVERRIDE*/void set f2(C value) {}
+  void set /*error:INVALID_OVERRIDE*/f2(C value) {}
   void set f3(value) {}
   void set f4(dynamic value) {}
   set f5(B value) {}
@@ -4265,68 +4265,6 @@
     await check();
   }
 
-  test_strictInference_collectionLiterals() async {
-    addFile(r'''
-main() {
-  var emptyList = /*info:INFERENCE_FAILURE_ON_COLLECTION_LITERAL*/[];
-  var emptyMap = /*info:INFERENCE_FAILURE_ON_COLLECTION_LITERAL*/{};
-  final finalEmptyList = /*info:INFERENCE_FAILURE_ON_COLLECTION_LITERAL*/[];
-  final finalEmptyMap = /*info:INFERENCE_FAILURE_ON_COLLECTION_LITERAL*/{};
-  const constEmptyList = /*info:INFERENCE_FAILURE_ON_COLLECTION_LITERAL*/[];
-  const constEmptyMap = /*info:INFERENCE_FAILURE_ON_COLLECTION_LITERAL*/{};
-
-  void listFunction(
-      [list = /*info:INFERENCE_FAILURE_ON_COLLECTION_LITERAL*/const []]) => print(list);
-  void mapFunction(
-      [map = /*info:INFERENCE_FAILURE_ON_COLLECTION_LITERAL*/const {}]) => print(map);
-
-  var conditionalEmptyList =
-      "a" == "b" ? [1, 2, 3] : /*info:INFERENCE_FAILURE_ON_COLLECTION_LITERAL*/[];
-
-  dynamic returnsList1() => /*info:INFERENCE_FAILURE_ON_COLLECTION_LITERAL*/[];
-  Object returnsList2() => [];
-  void returnsList3() => [];
-
-  var onlyInnermostEmptyCollections = {
-    /*info:INFERENCE_FAILURE_ON_COLLECTION_LITERAL*/[]:
-        /*info:INFERENCE_FAILURE_ON_COLLECTION_LITERAL*/{}
-  };
-
-  // Inference has enough info in all of the cases below.
-  var upwardsInfersDynamicList = [42 as dynamic];
-  var upwardsInfersDynamicList2 = [42 as dynamic, 43 as dynamic];
-  var upwardsInfersDynamicList3 = [42 , 43.0];
-  var upwardsInfersDynamicSet = {42 as dynamic};
-
-  // Upwards inference provides correct types.
-  dynamic d;
-  var upwardsInfersDynamicMap1 = {d: 2};
-  var upwardsInfersDynamicMap2 = {4: d};
-  var upwardsInfersDynamicMap3 = {d: d};
-  var listWithElements = [1, 2, 3];
-
-  // The type of the right side of `??` is inferred from the left.
-  var nullAwareEmptyList = [1, 2, 3] ?? [];
-
-  // Type arguments provide types.
-  var typeArgList = <dynamic>[];
-  var typeArgSet = <dynamic>{};
-  var typeArgMap = <dynamic, dynamic>{};
-
-  // Downwards inference provides correct types.
-  Set<dynamic> downwardsInfersDynamicSet = {};
-  Map<dynamic, dynamic> downwardsInfersDynamicDynamicMap = {};
-  List<int> downwardsInfersIntList = [];
-  Set<int> downwardsInfersIntSet = {};
-
-  // The type of `set` is `Set<dynamic>`.
-  int setLength(Set set) => set.length;
-  setLength({});
-}
-    ''');
-    await check(strictInference: true);
-  }
-
   test_strictInference_instanceCreation() async {
     addFile(r'''
 class C<T> {
@@ -4343,238 +4281,14 @@
   var explicitDynamicIsOK = C<dynamic>(42);
 
   var rawConstructorCall = /*info:INFERENCE_FAILURE_ON_INSTANCE_CREATION*/C();
-  var upwardsInfersDynamic = /*info:INFERENCE_FAILURE_ON_INSTANCE_CREATION*/C(42 as dynamic);
-  var namedConstructor = /*info:INFERENCE_FAILURE_ON_INSTANCE_CREATION*/C.of(42 as dynamic);
   var factoryConstructor = /*info:INFERENCE_FAILURE_ON_INSTANCE_CREATION*/C.from(42);
-}
-    ''');
-    await check(strictInference: true);
-  }
-
-  test_strictInference_instanceCreation_optionalTypeArgs() async {
-    addMetaPackage();
-    addFile(r'''
-import 'package:meta/meta.dart';
-@optionalTypeArgs
-class C<T> {
-  C([T t]);
-  C.of(T t);
-  factory C.from(Object e) => C();
-}
-
-main() {
-  var rawConstructorCall = C();
   var upwardsInfersDynamic = C(42 as dynamic);
   var namedConstructor = C.of(42 as dynamic);
-  var factoryConstructor = C.from(42);
 }
     ''');
     await check(strictInference: true);
   }
 
-  test_strictRawTypes_classes() async {
-    addFile(r'''
-class C<T> {
-  C([T t]);
-}
-
-class M<T> {}
-
-class ExtendRawType extends /*info:STRICT_RAW_TYPE*/C {}
-class MixinRawType extends Object with /*info:STRICT_RAW_TYPE*/M {}
-class ImplementRawType implements /*info:STRICT_RAW_TYPE*/C {}
-class MixinApplicationRawType = Object with /*info:STRICT_RAW_TYPE*/M;
-
-class ClassWithNumBound<T extends num> {}
-class ClassWithObjectBound<T extends Object> {}
-class ClassWithDynamicBound<T extends dynamic> {}
-
-class ClassWithRawTypeBound<T extends /*info:STRICT_RAW_TYPE*/List> {}
-
-/*info:STRICT_RAW_TYPE*/C topLevelField;
-/*info:STRICT_RAW_TYPE*/C get topLevelGetter => null;
-set topLevelSetter(/*info:STRICT_RAW_TYPE*/C c) {}
-
-/*info:STRICT_RAW_TYPE*/C returnType() => null;
-parameterType(/*info:STRICT_RAW_TYPE*/C c) {}
-
-C<int> explicitTypeArgsAreOK;
-
-main() {
-  {
-    ClassWithNumBound classWithNumBoundOK;
-    ClassWithObjectBound classWithObjectBoundOK;
-    /*info:STRICT_RAW_TYPE*/ClassWithDynamicBound classWithDynamicBound;
-    /*info:STRICT_RAW_TYPE*/C rawConstructorCallFromType = C();
-  }
-
-  {
-    // These should be allowed:
-    List<int> downwardsInferenceIsOK = [];
-    List<dynamic> downwardsInferenceDynamicIsOK = [];
-    var upwardsInferNonDynamicIsOK = [42];
-    var explicitDynamicIsOK = <dynamic>[42];
-
-    var rawListOfLists = </*info:STRICT_RAW_TYPE*/List>[];
-    /*info:STRICT_RAW_TYPE*/List rawListFromType = [];
-  }
-
-  {
-    // These should be allowed:
-    List<int> downwardsInferenceIsOK = [];
-    List<dynamic> downwardsInferenceDynamicIsOK = [];
-    var upwardsInferNonDynamicIsOK = [42];
-    var explicitDynamicIsOK = <dynamic>[42];
-
-    var rawListOfLists = </*info:STRICT_RAW_TYPE*/List>[];
-    /*info:STRICT_RAW_TYPE*/List rawListFromType = [];
-  }
-
-  {
-    // These should be allowed:
-    Set<int> downwardsInferenceIsOK = {};
-    Set<dynamic> downwardsInferenceDynamicIsOK = {};
-    var upwardsInferNonDynamicIsOK = {42};
-    var explicitDynamicIsOK = <dynamic>{42};
-
-    var rawSetOfSets = </*info:STRICT_RAW_TYPE*/Set>{};
-    /*info:STRICT_RAW_TYPE*/Set rawSetFromType = {};
-  }
-
-  {
-    // These should be allowed:
-    Map<int, int> downwardsInferenceIsOK = {};
-    Map<dynamic, int> downwardsInferenceDynamicIsOK1 = {};
-    Map<int, dynamic> downwardsInferenceDynamicIsOK2 = {};
-    Map<dynamic, dynamic> downwardsInferenceDynamicIsOK3 = {};
-
-    var upwardsInferNonDynamicIsOK = {4: 2};
-    var explicitDynamicIsOK = <dynamic, dynamic>{4: 2};
-
-    var rawMapOfMaps = </*info:STRICT_RAW_TYPE*/Map>{};
-    /*info:STRICT_RAW_TYPE*/Map rawMapFromType = {};
-  }
-
-  {
-    Object isCheck;
-    if (isCheck is /*info:STRICT_RAW_TYPE_IN_IS*/List) {}
-    if (isCheck is List</*info:STRICT_RAW_TYPE_IN_IS*/List>) {}
-    if (isCheck is /*info:STRICT_RAW_TYPE_IN_IS*/C) {}
-
-    if (isCheck is List<dynamic>) {}
-    if (isCheck is List<int>) {}
-    if (isCheck is C<dynamic>) {}
-    if (isCheck is C<int>) {}
-  }
-
-  {
-    Object asCheck;
-    var asList = asCheck as /*info:STRICT_RAW_TYPE_IN_AS*/List;
-    var asMap = asCheck as Map<dynamic, /*info:STRICT_RAW_TYPE_IN_AS*/List>;
-    var asC = asCheck as /*info:STRICT_RAW_TYPE_IN_AS*/C;
-  }
-}
-    ''');
-    await check(strictRawTypes: true);
-  }
-
-  test_strictRawTypes_classes_optionalTypeArgs() async {
-    addMetaPackage();
-    addFile(r'''
-import 'package:meta/meta.dart';
-@optionalTypeArgs
-class C<T> {
-  C([T t]);
-}
-
-@optionalTypeArgs
-class M<T> {}
-
-class ExtendRawType extends C {}
-class MixinRawType extends Object with M {}
-class ImplementRawType implements C {}
-class MixinApplicationRawType = Object with M;
-
-C topLevelField;
-C get topLevelGetter => null;
-set topLevelSetter(C c) {}
-
-C returnType() => null;
-parameterType(C c) {}
-
-C<int> explicitTypeArgsAreOK;
-
-main() {
-  // These should be allowed:
-  C<int> downwardsInferenceIsOK = C();
-  C<dynamic> downwardsInferenceDynamicIsOK = C();
-  var inferredFromConstructorParameterIsOK = C(42);
-  var explicitDynamicIsOK = C<dynamic>(42);
-
-  var rawConstructorCall = C();
-  C rawConstructorCallFromType = C();
-  var upwardsInfersDynamic = C(42 as dynamic);
-
-  Object isChecksAreAllowed;
-  if (isChecksAreAllowed is C) {}
-}
-    ''');
-
-    await check(strictRawTypes: true);
-  }
-
-  test_strictRawTypes_typedefs() async {
-    addFile(r'''
-typedef T F1<T>(T _);
-typedef F2<T> = T Function(T);
-typedef G1<T> = S Function<S>(T);
-typedef G2<T> = S Function<S>(S); // right side does not use `T`
-
-typedef G3 = T Function<T>(T); // typedef has no type params.
-
-testTypedefs() {
-  /*info:STRICT_RAW_TYPE*/F1 rawTypedefDart1Syntax;
-  /*info:STRICT_RAW_TYPE*/F2 rawTypedefDart2Syntax;
-  /*info:STRICT_RAW_TYPE*/G1 rawTypedefGenericFunction;
-  /*info:STRICT_RAW_TYPE*/G2 rawTypedefGenericFunction2;
-  {
-    F1<dynamic> explicitTypedefDart1SyntaxIsOK;
-    F2<dynamic> explicitTypedefDart2SyntaxIsOK;
-    G1<dynamic> explicitTypedefGenericFunctionIsOK;
-    G2<dynamic> explicitTypedefGenericFunction2IsOK;
-    G3 typedefWithoutTypeParamsIsOK;
-  }
-  {
-    F1<int> explicitTypedefDart1SyntaxIsOK;
-    F2<int> explicitTypedefDart2SyntaxIsOK;
-    G1<int> explicitTypedefGenericFunctionIsOK;
-    G2<int> explicitTypedefGenericFunction2IsOK;
-  }
-}
-    ''');
-    await check(strictRawTypes: true);
-  }
-
-  test_strictRawTypes_typedefs_optionalTypeArgs() async {
-    addMetaPackage();
-    addFile(r'''
-import 'package:meta/meta.dart';
-
-@optionalTypeArgs typedef T F1<T>(T _);
-@optionalTypeArgs typedef F2<T> = T Function(T);
-@optionalTypeArgs typedef G1<T> = S Function<S>(T);
-@optionalTypeArgs typedef G2<T> = S Function<S>(S);
-
-testTypedefs() {
-  F1 rawTypedefDart1Syntax;
-  F2 rawTypedefDart2Syntax;
-  G1 rawTypedefGenericFunction;
-  G2 rawTypedefGenericFunction2;
-}
-    ''');
-    await check(strictRawTypes: true);
-  }
-
   test_superCallPlacement() async {
     await checkFile('''
 class Base {
@@ -5174,7 +4888,7 @@
 }
 
 class B extends A {
-  /*error:INVALID_OVERRIDE*/T method<T>(T x) => x;
+  T /*error:INVALID_OVERRIDE*/method<T>(T x) => x;
 }
     ''');
   }
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index 94feba2..db5ceab 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -429,12 +429,12 @@
 }
 
 class C1 implements A, B {
-  /*error:INVALID_OVERRIDE,error:INVALID_OVERRIDE*/get a => null;
+  get /*error:INVALID_OVERRIDE,error:INVALID_OVERRIDE*/a => null;
 }
 
 // Still ambiguous
 class C2 implements B, A {
-  /*error:INVALID_OVERRIDE,error:INVALID_OVERRIDE*/get a => null;
+  get /*error:INVALID_OVERRIDE,error:INVALID_OVERRIDE*/a => null;
 }
 ''');
   }
@@ -466,7 +466,7 @@
 }
 
 class C2 implements A, B {
-  /*error:INVALID_OVERRIDE,error:INVALID_OVERRIDE*/get a => null;
+  get /*error:INVALID_OVERRIDE,error:INVALID_OVERRIDE*/a => null;
 }
 ''');
   }
@@ -751,7 +751,7 @@
 }
 
 class B implements A {
-  /*error:INVALID_OVERRIDE*/dynamic get x => 3;
+  dynamic get /*error:INVALID_OVERRIDE*/x => 3;
 }
 
 foo() {
@@ -1955,8 +1955,8 @@
   dynamic g(int x) => x;
 }
 class D extends C {
-  /*error:INVALID_OVERRIDE*/T m<T>(T x) => x;
-  /*error:INVALID_OVERRIDE*/T g<T>(T x) => x;
+  T /*error:INVALID_OVERRIDE*/m<T>(T x) => x;
+  T /*error:INVALID_OVERRIDE*/g<T>(T x) => x;
 }
 main() {
   int y = /*info:DYNAMIC_CAST*/(/*info:UNNECESSARY_CAST*/new D() as C).m(42);
@@ -2488,56 +2488,6 @@
 ''');
   }
 
-  test_inferredType_usesSyntheticFunctionType() async {
-    var mainUnit = await checkFileElement('''
-int f() => null;
-String g() => null;
-var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
-''');
-    var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), 'List<Object Function()>');
-  }
-
-  test_inferredType_usesSyntheticFunctionType_functionTypedParam() async {
-    var mainUnit = await checkFileElement('''
-int f(int x(String y)) => null;
-String g(int x(String y)) => null;
-var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
-''');
-    var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), 'List<Object Function(int Function(String))>');
-  }
-
-  test_inferredType_usesSyntheticFunctionType_namedParam() async {
-    var mainUnit = await checkFileElement('''
-int f({int x}) => null;
-String g({int x}) => null;
-var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
-''');
-    var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), 'List<Object Function({x: int})>');
-  }
-
-  test_inferredType_usesSyntheticFunctionType_positionalParam() async {
-    var mainUnit = await checkFileElement('''
-int f([int x]) => null;
-String g([int x]) => null;
-var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
-''');
-    var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), 'List<Object Function([int])>');
-  }
-
-  test_inferredType_usesSyntheticFunctionType_requiredParam() async {
-    var mainUnit = await checkFileElement('''
-int f(int x) => null;
-String g(int x) => null;
-var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
-''');
-    var v = mainUnit.topLevelVariables[0];
-    expect(v.type.toString(), 'List<Object Function(int)>');
-  }
-
   test_inferFromComplexExpressionsIfOuterMostValueIsPrecise() async {
     await checkFileElement('''
 class A { int x; B operator+(other) => null; }
@@ -3077,6 +3027,56 @@
     expect(x.type.toString(), 'Map<String, int Function()>');
   }
 
+  test_inferredType_usesSyntheticFunctionType() async {
+    var mainUnit = await checkFileElement('''
+int f() => null;
+String g() => null;
+var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.type.toString(), 'List<Object Function()>');
+  }
+
+  test_inferredType_usesSyntheticFunctionType_functionTypedParam() async {
+    var mainUnit = await checkFileElement('''
+int f(int x(String y)) => null;
+String g(int x(String y)) => null;
+var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.type.toString(), 'List<Object Function(int Function(String))>');
+  }
+
+  test_inferredType_usesSyntheticFunctionType_namedParam() async {
+    var mainUnit = await checkFileElement('''
+int f({int x}) => null;
+String g({int x}) => null;
+var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.type.toString(), 'List<Object Function({x: int})>');
+  }
+
+  test_inferredType_usesSyntheticFunctionType_positionalParam() async {
+    var mainUnit = await checkFileElement('''
+int f([int x]) => null;
+String g([int x]) => null;
+var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.type.toString(), 'List<Object Function([int])>');
+  }
+
+  test_inferredType_usesSyntheticFunctionType_requiredParam() async {
+    var mainUnit = await checkFileElement('''
+int f(int x) => null;
+String g(int x) => null;
+var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
+''');
+    var v = mainUnit.topLevelVariables[0];
+    expect(v.type.toString(), 'List<Object Function(int)>');
+  }
+
   test_inferredType_viaClosure_multipleLevelsOfNesting() async {
     var mainUnit = await checkFileElement('''
 class C {
@@ -3400,7 +3400,7 @@
 }
 
 class B implements A<int> {
-  /*error:INVALID_OVERRIDE*/dynamic get x => 3;
+  dynamic get /*error:INVALID_OVERRIDE*/x => 3;
 }
 
 foo() {
diff --git a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
index 2edf77f..0a8d7ee 100644
--- a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
+++ b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
@@ -224,7 +224,6 @@
 class AbstractStrongTest with ResourceProviderMixin {
   bool _checkCalled = true;
 
-  AnalysisContext _context = null;
   AnalysisDriver _driver = null;
 
   Map<String, List<Folder>> packageMap;
@@ -323,8 +322,6 @@
         return code.errorSeverity.ordinal > ErrorSeverity.INFO.ordinal ||
             code == HintCode.INFERENCE_FAILURE_ON_COLLECTION_LITERAL ||
             code == HintCode.INFERENCE_FAILURE_ON_INSTANCE_CREATION ||
-            code == HintCode.STRICT_RAW_TYPE_IN_AS ||
-            code == HintCode.STRICT_RAW_TYPE_IN_IS ||
             code == HintCode.STRICT_RAW_TYPE;
       }
       return true;
@@ -374,7 +371,6 @@
   void tearDown() {
     // This is a sanity check, in case only addFile is called.
     expect(_checkCalled, true, reason: 'must call check() method in test case');
-    _context?.dispose();
     _driver?.dispose();
     AnalysisEngine.instance.clearCaches();
   }
diff --git a/pkg/analyzer/test/test_all.dart b/pkg/analyzer/test/test_all.dart
index 7694f2f..1daab29 100644
--- a/pkg/analyzer/test/test_all.dart
+++ b/pkg/analyzer/test/test_all.dart
@@ -4,7 +4,6 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'cancelable_future_test.dart' as cancelable_future;
 import 'dart/test_all.dart' as dart;
 import 'error/test_all.dart' as error;
 import 'file_system/test_all.dart' as file_system;
@@ -19,7 +18,6 @@
 
 main() {
   defineReflectiveSuite(() {
-    cancelable_future.main();
     dart.main();
     error.main();
     file_system.main();
diff --git a/pkg/analyzer/test/utils.dart b/pkg/analyzer/test/utils.dart
index 9681e6c..bfb9fe1 100644
--- a/pkg/analyzer/test/utils.dart
+++ b/pkg/analyzer/test/utils.dart
@@ -6,8 +6,8 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
-import 'package:analyzer/src/generated/testing/element_search.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/testing/element_search.dart';
 import 'package:test/test.dart';
 
 /**
@@ -237,12 +237,12 @@
   /**
    * Primitive assertion for the list type
    */
-  Asserter<DartType> get isList => hasElementOf(_typeProvider.listType);
+  Asserter<DartType> get isList => hasElement(_typeProvider.listElement);
 
   /**
    * Primitive assertion for the map type
    */
-  Asserter<DartType> get isMap => hasElementOf(_typeProvider.mapType);
+  Asserter<DartType> get isMap => hasElement(_typeProvider.mapElement);
 
   /**
    * Primitive assertion for the Null type
@@ -271,12 +271,6 @@
       (DartType type) => expect(expected, type.element);
 
   /**
-   * Assert that a type has the element that is equal to the element of the
-   * given [type].
-   */
-  Asserter<DartType> hasElementOf(DartType type) => hasElement(type.element);
-
-  /**
    * Given assertions for the argument and return types, produce an
    *  assertion over unary function types.
    */
diff --git a/pkg/analyzer/test/verify_diagnostics_test.dart b/pkg/analyzer/test/verify_diagnostics_test.dart
index b8ce223..1340172 100644
--- a/pkg/analyzer/test/verify_diagnostics_test.dart
+++ b/pkg/analyzer/test/verify_diagnostics_test.dart
@@ -9,42 +9,35 @@
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/test_utilities/package_mixin.dart';
 import 'package:path/path.dart';
+import 'package:pub_semver/src/version_constraint.dart';
 import 'package:test/test.dart';
 
 import '../tool/diagnostics/generate.dart';
 import 'src/dart/resolution/driver_resolution.dart';
-import 'utils/package_root.dart' as package_root;
 
 /// Validate the documentation associated with the declarations of the error
 /// codes.
 void main() async {
   Context pathContext = PhysicalResourceProvider.INSTANCE.pathContext;
+  List<CodePath> codePaths = computeCodePaths();
   //
   // Validate that the input to the generator is correct.
   //
-  String packageRoot = pathContext.normalize(package_root.packageRoot);
-  String analyzerPath = pathContext.join(packageRoot, 'analyzer');
-  List<String> docPaths = [
-    pathContext.join(
-        analyzerPath, 'lib', 'src', 'dart', 'error', 'hint_codes.dart'),
-    pathContext.join(analyzerPath, 'lib', 'src', 'error', 'codes.dart'),
-  ];
-
-  DocumentationValidator validator = DocumentationValidator(docPaths);
-  validator.validate();
+  DocumentationValidator validator = DocumentationValidator(codePaths);
+  await validator.validate();
   //
   // Validate that the generator has been run.
   //
   if (pathContext.style != Style.windows) {
-    String outputPath =
-        pathContext.join(analyzerPath, 'tool', 'diagnostics', 'diagnostics.md');
     String actualContent = PhysicalResourceProvider.INSTANCE
-        .getFile(outputPath)
+        .getFile(computeOutputPath())
         .readAsStringSync();
 
     StringBuffer sink = StringBuffer();
-    DocumentationGenerator generator = DocumentationGenerator(docPaths);
+    DocumentationGenerator generator = DocumentationGenerator(codePaths);
     generator.writeDocumentation(sink);
     String expectedContent = sink.toString();
 
@@ -63,9 +56,18 @@
   /// The sequence used to mark the end of an error range.
   static const String errorRangeEnd = '!]';
 
+  /// A list of the diagnostic codes that are not being verified. These should
+  /// ony include docs that cannot be verified because of missing support in the
+  /// verifier.
+  static const List<String> unverifiedDocs = ['HintCode.DEPRECATED_MEMBER_USE'];
+
+  /// The prefix used on directive lines to indicate the uri of an auxiliary
+  /// file that is needed for testing purposes.
+  static const String uriDirectivePrefix = '%uri="';
+
   /// The absolute paths of the files containing the declarations of the error
   /// codes.
-  final List<String> docPaths;
+  final List<CodePath> codePaths;
 
   /// The buffer to which validation errors are written.
   final StringBuffer buffer = StringBuffer();
@@ -85,15 +87,16 @@
   bool hasWrittenCodeName = false;
 
   /// Initialize a newly created documentation validator.
-  DocumentationValidator(this.docPaths);
+  DocumentationValidator(this.codePaths);
 
   /// Validate the documentation.
-  void validate() async {
+  Future<void> validate() async {
     AnalysisContextCollection collection = new AnalysisContextCollection(
-        includedPaths: docPaths,
+        includedPaths:
+            codePaths.map((codePath) => codePath.documentationPath).toList(),
         resourceProvider: PhysicalResourceProvider.INSTANCE);
-    for (String docPath in docPaths) {
-      _validateFile(_parse(collection, docPath));
+    for (CodePath codePath in codePaths) {
+      await _validateFile(_parse(collection, codePath.documentationPath));
     }
     if (buffer.isNotEmpty) {
       fail(buffer.toString());
@@ -124,36 +127,68 @@
     return docs;
   }
 
-  _SnippetData _extractSnippetData(String snippet) {
+  _SnippetData _extractSnippetData(
+      String snippet, bool errorRequired, Map<String, String> auxiliaryFiles) {
     int rangeStart = snippet.indexOf(errorRangeStart);
     if (rangeStart < 0) {
-      _reportProblem('No error range in example');
-      return _SnippetData(snippet, -1, 0);
+      if (errorRequired) {
+        _reportProblem('No error range in example');
+      }
+      return _SnippetData(snippet, -1, 0, auxiliaryFiles);
     }
     int rangeEnd = snippet.indexOf(errorRangeEnd, rangeStart + 1);
     if (rangeEnd < 0) {
       _reportProblem('No end of error range in example');
-      return _SnippetData(snippet, -1, 0);
+      return _SnippetData(snippet, -1, 0, auxiliaryFiles);
     } else if (snippet.indexOf(errorRangeStart, rangeEnd) > 0) {
       _reportProblem('More than one error range in example');
     }
+    if (snippet.indexOf('extension') >= 0) {
+      DateTime.now();
+    }
     return _SnippetData(
         snippet.substring(0, rangeStart) +
-            snippet.substring(rangeStart + 1, rangeEnd) +
-            snippet.substring(rangeEnd + 1),
+            snippet.substring(rangeStart + errorRangeStart.length, rangeEnd) +
+            snippet.substring(rangeEnd + errorRangeEnd.length),
         rangeStart,
-        rangeEnd - rangeStart - 1);
+        rangeEnd - rangeStart - 2,
+        auxiliaryFiles);
   }
 
   /// Extract the snippets of Dart code between the start (inclusive) and end
   /// (exclusive) indexes.
-  List<String> _extractSnippets(List<String> lines, int start, int end) {
-    List<String> snippets = [];
-    int snippetStart = lines.indexOf('```dart', start);
-    while (snippetStart >= 0 && snippetStart < end) {
-      int snippetEnd = lines.indexOf('```', snippetStart + 1);
-      snippets.add(lines.sublist(snippetStart + 1, snippetEnd).join('\n'));
-      snippetStart = lines.indexOf('```dart', snippetEnd + 1);
+  List<_SnippetData> _extractSnippets(
+      List<String> lines, int start, int end, bool errorRequired) {
+    List<_SnippetData> snippets = [];
+    Map<String, String> auxiliaryFiles = <String, String>{};
+    int currentStart = -1;
+    for (int i = start; i < end; i++) {
+      String line = lines[i];
+      if (line == '```') {
+        if (currentStart < 0) {
+          _reportProblem('Snippet without file type on line $i.');
+          return snippets;
+        }
+        String secondLine = lines[currentStart + 1];
+        if (secondLine.startsWith(uriDirectivePrefix)) {
+          String name = secondLine.substring(
+              uriDirectivePrefix.length, secondLine.length - 1);
+          String content = lines.sublist(currentStart + 2, i).join('\n');
+          auxiliaryFiles[name] = content;
+        } else if (lines[currentStart] == '```dart') {
+          String content = lines.sublist(currentStart + 1, i).join('\n');
+          snippets
+              .add(_extractSnippetData(content, errorRequired, auxiliaryFiles));
+          auxiliaryFiles = <String, String>{};
+        }
+        currentStart = -1;
+      } else if (line.startsWith('```')) {
+        if (currentStart >= 0) {
+          _reportProblem('Snippet before line $i was not closed.');
+          return snippets;
+        }
+        currentStart = i;
+      }
     }
     return snippets;
   }
@@ -185,6 +220,7 @@
     }
     buffer.writeln('    $problem');
     for (AnalysisError error in errors) {
+      buffer.write('      ');
       buffer.write(error.errorCode);
       buffer.write(' (');
       buffer.write(error.offset);
@@ -197,7 +233,7 @@
 
   /// Extract documentation from the file that was parsed to produce the given
   /// [result].
-  void _validateFile(ParsedUnitResult result) {
+  Future<void> _validateFile(ParsedUnitResult result) async {
     filePath = result.path;
     hasWrittenFilePath = false;
     CompilationUnit unit = result.unit;
@@ -211,22 +247,24 @@
               VariableDeclaration variable = member.fields.variables[0];
               String variableName = variable.name.name;
               codeName = '$className.$variableName';
+              if (unverifiedDocs.contains(codeName)) {
+                continue;
+              }
               hasWrittenCodeName = false;
 
               int exampleStart = docs.indexOf('#### Example');
               int fixesStart = docs.indexOf('#### Common fixes');
 
-              List<String> exampleSnippets =
-                  _extractSnippets(docs, exampleStart + 1, fixesStart);
-              for (String snippet in exampleSnippets) {
-                _SnippetData data = _extractSnippetData(snippet);
-                _validateSnippet(data.snippet, data.offset, data.length);
+              List<_SnippetData> exampleSnippets =
+                  _extractSnippets(docs, exampleStart + 1, fixesStart, true);
+              for (_SnippetData snippet in exampleSnippets) {
+                await _validateSnippet(snippet);
               }
 
-              List<String> fixesSnippets =
-                  _extractSnippets(docs, fixesStart + 1, docs.length);
-              for (String snippet in fixesSnippets) {
-                _validateSnippet(snippet, -1, 0);
+              List<_SnippetData> fixesSnippets =
+                  _extractSnippets(docs, fixesStart + 1, docs.length, false);
+              for (_SnippetData snippet in fixesSnippets) {
+                await _validateSnippet(snippet);
               }
             }
           }
@@ -235,21 +273,19 @@
     }
   }
 
-  /// Resolve the [snippet]. If the [offset] is less than zero, then verify that
-  /// no diagnostics are reported. If the [offset] is greater than or equal to
-  /// zero, verify that one error whose name matches the current code is
-  /// reported at that offset with the given [length].
-  void _validateSnippet(String snippet, int offset, int length) async {
-    // TODO(brianwilkerson) Implement this.
-    DriverResolutionTest test = DriverResolutionTest();
+  /// Resolve the [snippet]. If the snippet's offset is less than zero, then
+  /// verify that no diagnostics are reported. If the offset is greater than or
+  /// equal to zero, verify that one error whose name matches the current code
+  /// is reported at that offset with the expected length.
+  Future<void> _validateSnippet(_SnippetData snippet) async {
+    _SnippetTest test = _SnippetTest(snippet);
     test.setUp();
-    test.addTestFile(snippet);
     await test.resolveTestFile();
     List<AnalysisError> errors = test.result.errors;
     int errorCount = errors.length;
-    if (offset < 0) {
+    if (snippet.offset < 0) {
       if (errorCount > 0) {
-        _reportProblem('Expected no errors but found $errorCount.',
+        _reportProblem('Expected no errors but found $errorCount:',
             errors: errors);
       }
     } else {
@@ -257,20 +293,20 @@
         _reportProblem('Expected one error but found none.');
       } else if (errorCount == 1) {
         AnalysisError error = errors[0];
-        if (error.errorCode != codeName) {
+        if (error.errorCode.uniqueName != codeName) {
           _reportProblem(
               'Expected an error with code $codeName, found ${error.errorCode}.');
         }
-        if (error.offset != offset) {
+        if (error.offset != snippet.offset) {
           _reportProblem(
-              'Expected an error at $offset, found ${error.offset}.');
+              'Expected an error at ${snippet.offset}, found ${error.offset}.');
         }
-        if (error.length != length) {
+        if (error.length != snippet.length) {
           _reportProblem(
-              'Expected an error of length $length, found ${error.length}.');
+              'Expected an error of length ${snippet.length}, found ${error.length}.');
         }
       } else {
-        _reportProblem('Expected one error but found $errorCount.',
+        _reportProblem('Expected one error but found $errorCount:',
             errors: errors);
       }
     }
@@ -280,9 +316,60 @@
 /// A data holder used to return multiple values when extracting an error range
 /// from a snippet.
 class _SnippetData {
-  final String snippet;
+  final String content;
   final int offset;
   final int length;
+  final Map<String, String> auxiliaryFiles;
 
-  _SnippetData(this.snippet, this.offset, this.length);
+  _SnippetData(this.content, this.offset, this.length, this.auxiliaryFiles);
+}
+
+/// A test class that creates an environment suitable for analyzing the
+/// snippets.
+class _SnippetTest extends DriverResolutionTest with PackageMixin {
+  /// The snippet being tested.
+  final _SnippetData snippet;
+
+  @override
+  AnalysisOptionsImpl analysisOptions = AnalysisOptionsImpl();
+
+  /// Initialize a newly created test to test the given [snippet].
+  _SnippetTest(this.snippet) {
+    analysisOptions.enabledExperiments = ['extension-methods'];
+    String pubspecContent = snippet.auxiliaryFiles['pubspec.yaml'];
+    if (pubspecContent != null) {
+      for (String line in pubspecContent.split('\n')) {
+        if (line.indexOf('sdk:') > 0) {
+          int start = line.indexOf("'") + 1;
+          String constraint = line.substring(start, line.indexOf("'", start));
+          analysisOptions.sdkVersionConstraint =
+              VersionConstraint.parse(constraint);
+        }
+      }
+    }
+  }
+
+  @override
+  void setUp() {
+    super.setUp();
+    addMetaPackage();
+    _createAuxiliaryFiles(snippet.auxiliaryFiles);
+    addTestFile(snippet.content);
+  }
+
+  void _createAuxiliaryFiles(Map<String, String> auxiliaryFiles) {
+    Map<String, String> packageMap = {};
+    for (String uri in auxiliaryFiles.keys) {
+      if (uri.startsWith('package:')) {
+        int slash = uri.indexOf('/');
+        String packageName = uri.substring(8, slash);
+        String libPath = packageMap.putIfAbsent(
+            packageName, () => addPubPackage(packageName).path);
+        String relativePath = uri.substring(slash + 1);
+        newFile('$libPath/$relativePath', content: auxiliaryFiles[uri]);
+      } else {
+        newFile('/test/$uri', content: auxiliaryFiles[uri]);
+      }
+    }
+  }
 }
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index aa77a12..46b5264 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -62,6 +62,66 @@
 doesn't conform to the language specification or
 that might work in unexpected ways.
 
+### ambiguous_extension_member_access
+
+_A member named '{0}' is defined in extensions '{1}' and '{2}' and neither is
+more specific._
+
+#### Description
+
+When code refers to a member of an object (for example, `o.m()` or `o.m` or
+`o[i]`) where the static type of `o` doesn't declare the member (`m` or
+`[]`, for example), then the analyzer tries to find the member in an
+extension. For example, if the member is `m`, then the analyzer looks for
+extensions that declare a member named `m` and have an extended type that
+the static type of `o` can be assigned to. When there's more than one such
+extension in scope, the extension whose extended type is most specific is
+selected.
+
+The analyzer produces this diagnostic when none of the extensions has an
+extended type that's more specific than the extended types of all of the
+other extensions, making the reference to the member ambiguous.
+
+#### Example
+
+The following code produces this diagnostic because there's no way to
+choose between the member in `E1` and the member in `E2`:
+
+{% prettify dart %}
+extension E1 on String {
+  int get charCount => 1;
+}
+
+extension E2 on String {
+  int get charCount => 2;
+}
+
+void f(String s) {
+  print(s.[!charCount!]);
+}
+{% endprettify %}
+
+#### Common fixes
+
+If you don't need both extensions, then you can delete or hide one of them.
+
+If you need both, then explicitly select the one you want to use by using
+an extension override:
+
+{% prettify dart %}
+extension E1 on String {
+  int get charCount => length;
+}
+
+extension E2 on String {
+  int get charCount => length;
+}
+
+void f(String s) {
+  print(E2(s).charCount);
+}
+{% endprettify %}
+
 ### ambiguous_set_or_map_literal_both
 
 _This literal contains both 'Map' and 'Iterable' spreads, which makes it
@@ -175,7 +235,7 @@
 
 {% prettify dart %}
 union(a, b) {
-  var x = {...a, ...b};
+  var x = [!{...a, ...b}!];
   return x;
 }
 {% endprettify %}
@@ -203,8 +263,8 @@
 The following code produces this diagnostic:
 
 {% prettify dart %}
-int f(int x) => x;
-num g(num y) => f([!y!]);
+String f(String x) => x;
+String g(num y) => f([!y!]);
 {% endprettify %}
 
 #### Common fixes
@@ -213,8 +273,8 @@
 example above you might be able to change the type of the parameter `y`:
 
 {% prettify dart %}
-int f(int x) => x;
-int g(int y) => f(y);
+String f(String x) => x;
+String g(String y) => f(y);
 {% endprettify %}
 
 If that fix isn't possible, then add code to handle the case where the
@@ -222,15 +282,15 @@
 types to the required type:
 
 {% prettify dart %}
-int f(int x) => x;
-num g(num y) => f(y.floor());
+String f(String x) => x;
+String g(num y) => f(y.toString());
 {% endprettify %}
 
 Another approach is to add explicit type tests and fallback code:
 
 {% prettify dart %}
-int f(int x) => x;
-num g(num y) => f(y is int ? y : 0);
+String f(String x) => x;
+String g(num y) => f(y is String ? y : '');
 {% endprettify %}
 
 If you believe that the runtime type of the argument will always be the
@@ -238,8 +298,8 @@
 an exception thrown at runtime if you're wrong, then add an explicit cast:
 
 {% prettify dart %}
-int f(int x) => x;
-num g(num y) => f(y as int);
+String f(String x) => x;
+String g(num y) => f(y as String);
 {% endprettify %}
 
 ### const_initialized_with_non_constant_value
@@ -380,7 +440,7 @@
 var map = <String, int>{'a': 0, 'b': 1, [!'c'!]};
 {% endprettify %}
 
-#### Common fix
+#### Common fixes
 
 If the expression is intended to compute either a key or a value in an
 entry, fix the issue by replacing the expression with the key or the value.
@@ -390,6 +450,335 @@
 var map = <String, int>{'a': 0, 'b': 1, 'c': 2};
 {% endprettify %}
 
+### extension_conflicting_static_and_instance
+
+_Extension '{0}' can't define static member '{1}' and an instance member with
+the same name._
+
+#### Description
+
+The analyzer produces this diagnostic when an extension declaration
+contains both an instance member and a static member that have the same
+name. The instance member and the static member can't have the same name
+because it's unclear which member is being referenced by an unqualified use
+of the name within the body of the extension.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+extension E on Object {
+  int get a => 0;
+  static int [!a!]() => 0;
+}
+{% endprettify %}
+
+#### Common fixes
+
+Rename or remove one of the members:
+
+{% prettify dart %}
+extension E on Object {
+  int get a => 0;
+  static int b() => 0;
+}
+{% endprettify %}
+
+### extension_declares_abstract_member
+
+_Extensions can't declare abstract members._
+
+#### Description
+
+The analyzer produces this diagnostic when an abstract declaration is
+declared in an extension. Extensions can declare only concrete members.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+extension E on String {
+  int [!a!]();
+}
+{% endprettify %}
+
+#### Common fixes
+
+Either provide an implementation for the member or remove it.
+
+### extension_declares_constructor
+
+_Extensions can't declare constructors._
+
+#### Description
+
+The analyzer produces this diagnostic when a constructor declaration is
+found in an extension. It isn't valid to define a constructor because
+extensions aren't classes, and it isn't possible to create an instance of
+an extension.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+extension E on String {
+  [!E!]() : super();
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove the constructor or replace it with a static method.
+
+### extension_declares_instance_field
+
+_Extensions can't declare instance fields_
+
+#### Description
+
+The analyzer produces this diagnostic when an instance field declaration is
+found in an extension. It isn't valid to define an instance field because
+extensions can only add behavior, not state.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+extension E on String {
+  String [!s!];
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove the field, make it a static field, or convert it to be a getter,
+setter, or method.
+
+### extension_declares_member_of_object
+
+_Extensions can't declare members with the same name as a member declared by
+'Object'._
+
+#### Description
+
+The analyzer produces this diagnostic when an extension declaration
+declares a member with the same name as a member declared in the class
+`Object`. Such a member can never be used because the member in `Object` is
+always found first.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+extension E on String {
+  String [!toString!]() => this;
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove the member or rename it so that the name doesn't conflict with the
+member in `Object`:
+
+{% prettify dart %}
+extension E on String {
+  String displayString() => this;
+}
+{% endprettify %}
+
+### extension_override_access_to_static_member
+
+_An extension override can't be used to access a static member from an
+extension._
+
+#### Description
+
+The analyzer produces this diagnostic when an extension override is the
+target of the invocation of a static member. Similar to static members in
+classes, the static members of an extension should be accessed using the
+name of the extension, not an extension override.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+extension E on String {
+  static void staticMethod() {}
+}
+
+void f() {
+  E('').[!staticMethod!]();
+}
+{% endprettify %}
+
+#### Common fixes
+
+Replace the extension override with the name of the extension:
+
+{% prettify dart %}
+extension E on String {
+  static void staticMethod() {}
+}
+
+void f() {
+  E.staticMethod();
+}
+{% endprettify %}
+
+### extension_override_argument_not_assignable
+
+_The type of the argument to the extension override '{0}' isn't assignable to
+the extended type '{1}'._
+
+#### Description
+
+The analyzer produces this diagnostic when the argument to an extension
+override isn't assignable to the type being extended by the extension.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+extension E on String {
+  void method() {}
+}
+
+void f() {
+  E([!3!]).method();
+}
+{% endprettify %}
+
+#### Common fixes
+
+If you're using the correct extension, then update the argument to have the
+correct type:
+
+{% prettify dart %}
+extension E on String {
+  void method() {}
+}
+
+void f() {
+  E(3.toString()).method();
+}
+{% endprettify %}
+
+If there's a different extension that's valid for the type of the argument,
+then either replace the name of the extension or unwrap the target so that
+the correct extension is found.
+
+### extension_override_without_access
+
+_An extension override can only be used to access instance members._
+
+#### Description
+
+The analyzer produces this diagnostic when an extension override is found
+that isn't being used to access one of the members of the extension. The
+extension override syntax doesn't have any runtime semantics; it only
+controls which member is selected at compile time.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+extension E on int {
+  int get a => 0;
+}
+
+void f(int i) {
+  print([!E(i)!]);
+}
+{% endprettify %}
+
+#### Common fixes
+
+If you want to invoke one of the members of the extension, then add the
+invocation:
+
+{% prettify dart %}
+extension E on int {
+  int get a => 0;
+}
+
+void f(int i) {
+  print(E(i).a);
+}
+{% endprettify %}
+
+If you don't want to invoke a member, then unwrap the target:
+
+{% prettify dart %}
+extension E on int {
+  int get a => 0;
+}
+
+void f(int i) {
+  print(i);
+}
+{% endprettify %}
+
+### invalid_extension_argument_count
+
+_Extension overrides must have exactly one argument: the value of 'this' in the
+extension method._
+
+#### Description
+
+The analyzer produces this diagnostic when an extension override doesn't
+have exactly one argument. The argument is the expression used to compute
+the value of `this` within the extension method, so there must be one
+argument.
+
+#### Example
+
+The following code produces this diagnostic because there are no arguments:
+
+{% prettify dart %}
+extension E on String {
+  String join(String other) => '$this $other';
+}
+
+void f() {
+  E[!()!].join('b');
+}
+{% endprettify %}
+
+And, the following code produces this diagnostic because there's more than
+one argument:
+
+{% prettify dart %}
+extension E on String {
+  String join(String other) => '$this $other';
+}
+
+void f() {
+  E[!('a', 'b')!].join('c');
+}
+{% endprettify %}
+
+#### Common fixes
+
+Provide one argument for the extension override:
+
+{% prettify dart %}
+extension E on String {
+  String join(String other) => '$this $other';
+}
+
+void f() {
+  E('a').join('b');
+}
+{% endprettify %}
+
 ### invalid_literal_annotation
 
 _Only const constructors can have the `@literal` annotation._
@@ -404,6 +793,8 @@
 The following code produces this diagnostic:
 
 {% prettify dart %}
+import 'package:meta/meta.dart';
+
 [!@literal!]
 var x;
 {% endprettify %}
@@ -416,6 +807,37 @@
 var x;
 {% endprettify %}
 
+### invalid_use_of_covariant_in_extension
+
+_The 'covariant' keyword can't be used in an extension._
+
+#### Description
+
+The analyzer produces this diagnostic when a member declared inside an
+extension uses the keyword `covariant` in the declaration of a parameter.
+Extensions aren't classes and don't have subclasses, so the keyword serves
+no purpose.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+extension E on String {
+  void a([!covariant!] int i) {}
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove the 'covariant' keyword:
+
+{% prettify dart %}
+extension E on String {
+  void a(int i) {}
+}
+{% endprettify %}
+
 ### invocation_of_non_function
 
 _'{0}' isn't a function._
@@ -449,7 +871,7 @@
 
 #### Description
 
-Any function or method that doesn’t end with either an explicit return or a
+Any function or method that doesn't end with either an explicit return or a
 throw implicitly returns `null`. This is rarely the desired behavior. The
 analyzer produces this diagnostic when it finds an implicit return.
 
@@ -487,8 +909,8 @@
 even though it appears in an implicitly constant list literal:
 
 {% prettify dart %}
-int x = 2;
-const y = <int>[0, 1, [!x!]];
+var x = 2;
+var y = const <int>[0, 1, [!x!]];
 {% endprettify %}
 
 #### Common fixes
@@ -498,17 +920,17 @@
 declaration of `x`:
 
 {% prettify dart %}
-const int x = 2;
-const y = <int>[0, 1, x];
+const x = 2;
+var y = const <int>[0, 1, x];
 {% endprettify %}
 
 If the expression can't be made a constant, then the list can't be a
 constant either, so you must change the code so that the list isn't a
-constant. In the example above this means removing the `const` keyword from
-the declaration of `y`:
+constant. In the example above this means removing the `const` keyword
+before the list literal:
 
 {% prettify dart %}
-int x = 2;
+var x = 2;
 var y = <int>[0, 1, x];
 {% endprettify %}
 
@@ -555,9 +977,7 @@
 
 {% prettify dart %}
 f() {}
-main() {
-  [!f!] v = null;
-}
+g([!f!] v) {}
 {% endprettify %}
 
 #### Common fixes
@@ -583,7 +1003,7 @@
 var s = <String>{...[!m!]};
 {% endprettify %}
 
-#### Common fix
+#### Common fixes
 
 The most common fix is to replace the expression with one that produces an
 iterable object:
@@ -609,7 +1029,7 @@
 The following code produces this diagnostic because `f` is a function:
 
 {% prettify dart %}
-C f() {}
+C f() => null;
 
 class C {
   factory C() = [!f!];
@@ -628,13 +1048,328 @@
 the constructor to return the value from the constructor's body:
 
 {% prettify dart %}
-C f() {}
+C f() => null;
 
 class C {
   factory C() => f();
 }
 {% endprettify %}
 
+### sdk_version_async_exported_from_core
+
+_The class '{0}' wasn't exported from 'dart:core' until version 2.1, but this
+code is required to be able to run on earlier versions._
+
+#### Description
+
+The analyzer produces this diagnostic when either the class `Future` or
+`Stream` is referenced in a library that doesn't import `dart:async` in
+code that has an SDK constraint whose lower bound is less than 2.1.0. In
+earlier versions, these classes weren't defined in `dart:core`, so the
+import was necessary.
+
+#### Example
+
+Here's an example of a pubspec that defines an SDK constraint with a lower
+bound of less than 2.1.0:
+
+```yaml
+environment:
+  sdk: '>=2.0.0 <2.4.0'
+```
+
+In the package that has that pubspec, code like the following produces this
+diagnostic:
+
+{% prettify dart %}
+void f([!Future!] f) {}
+{% endprettify %}
+
+#### Common fixes
+
+If you don't need to support older versions of the SDK, then you can
+increase the SDK constraint to allow the classes to be referenced:
+
+```yaml
+environment:
+  sdk: '>=2.1.0 <2.4.0'
+```
+
+If you need to support older versions of the SDK, then import the
+`dart:async` library.
+
+{% prettify dart %}
+import 'dart:async';
+
+void f(Future f) {}
+{% endprettify %}
+
+### sdk_version_as_expression_in_const_context
+
+_The use of an as expression in a constant expression wasn't supported until
+version 2.3.2, but this code is required to be able to run on earlier versions._
+
+#### Description
+
+The analyzer produces this diagnostic when an as expression inside a
+[constant context](#constant-context) is found in code that has an SDK
+constraint whose lower bound is less than 2.3.2. Using an as expression in
+a [constant context](#constant-context) wasn't supported in earlier
+versions, so this code won't be able to run against earlier versions of the
+SDK.
+
+#### Example
+
+Here's an example of a pubspec that defines an SDK constraint with a lower
+bound of less than 2.3.2:
+
+```yaml
+environment:
+  sdk: '>=2.1.0 <2.4.0'
+```
+
+In the package that has that pubspec, code like the following generates
+this diagnostic:
+
+{% prettify dart %}
+const num n = 3;
+const int i = [!n as int!];
+{% endprettify %}
+
+#### Common fixes
+
+If you don't need to support older versions of the SDK, then you can
+ncrease the SDK constraint to allow the expression to be used:
+
+```yaml
+environment:
+  sdk: '>=2.3.2 <2.4.0'
+```
+
+If you need to support older versions of the SDK, then either rewrite the
+code to not use an as expression, or change the code so that the as
+expression is not in a [constant context](#constant-context).:
+
+{% prettify dart %}
+num x = 3;
+int y = x as int;
+{% endprettify %}
+
+### sdk_version_bool_operator_in_const_context
+
+_The use of the operator '{0}' for 'bool' operands in a constant context wasn't
+supported until version 2.3.2, but this code is required to be able to run on earlier versions._
+
+#### Description
+
+The analyzer produces this diagnostic when any use of the `&`, `|` or `^`
+operators on the class `bool` inside a
+[constant context](#constant-context) is found in code that has an SDK
+constraint whose lower bound is less than 2.3.2. Using these operators in a
+[constant context](#constant-context) wasn't supported in earlier versions,
+so this code won't be able to run against earlier versions of the SDK.
+
+#### Example
+
+Here's an example of a pubspec that defines an SDK constraint with a lower
+bound of less than 2.3.2:
+
+```yaml
+environment:
+  sdk: '>=2.1.0 <2.4.0'
+```
+
+In the package that has that pubspec, code like the following produces this
+diagnostic:
+
+{% prettify dart %}
+const bool a = true;
+const bool b = false;
+const bool c = a [!&!] b;
+{% endprettify %}
+
+#### Common fixes
+
+If you don't need to support older versions of the SDK, then you can
+increase the SDK constraint to allow the operators to be used:
+
+```yaml
+environment:
+ sdk: '>=2.3.2 <2.4.0'
+```
+
+If you need to support older versions of the SDK, then either rewrite the
+code to not use these operators, or change the code so that the expression
+is not in a [constant context](#constant-context).:
+
+{% prettify dart %}
+const bool a = true;
+const bool b = false;
+bool c = a & b;
+{% endprettify %}
+
+### sdk_version_eq_eq_operator_in_const_context
+
+_Using the operator '==' for non-primitive types wasn't supported until version
+2.3.2, but this code is required to be able to run on earlier versions._
+
+#### Description
+
+The analyzer produces this diagnostic when the operator `==` is used on a
+non-primitive type inside a [constant context](#constant-context) is found
+in code that has an SDK constraint whose lower bound is less than 2.3.2.
+Using this operator in a [constant context](#constant-context) wasn't
+supported in earlier versions, so this code won't be able to run against
+earlier versions of the SDK.
+
+#### Example
+
+Here's an example of a pubspec that defines an SDK constraint with a lower
+bound of less than 2.3.2:
+
+```yaml
+environment:
+  sdk: '>=2.1.0 <2.4.0'
+```
+
+In the package that has that pubspec, code like the following produces this
+diagnostic:
+
+{% prettify dart %}
+class C {}
+const C a = null;
+const C b = null;
+const bool same = a [!==!] b;
+{% endprettify %}
+
+#### Common fixes
+
+If you don't need to support older versions of the SDK, then you can
+increase the SDK constraint to allow the operator to be used:
+
+```yaml
+environment:
+  sdk: '>=2.3.2 <2.4.0'
+```
+
+If you need to support older versions of the SDK, then either rewrite the
+code to not use the `==` operator, or change the code so that the
+expression is not in a [constant context](#constant-context).:
+
+{% prettify dart %}
+class C {}
+const C a = null;
+const C b = null;
+bool same = a == b;
+{% endprettify %}
+
+### sdk_version_extension_methods
+
+_Extension methods weren't supported until version 2.6.0, but this code is
+required to be able to run on earlier versions._
+
+#### Description
+
+The analyzer produces this diagnostic when an extension declaration or an
+extension override is found in code that has an SDK constraint whose lower
+bound is less than 2.6.0. Using extensions wasn't supported in earlier
+versions, so this code won't be able to run against earlier versions of the
+SDK.
+
+#### Example
+
+Here's an example of a pubspec that defines an SDK constraint with a lower
+bound of less than 2.6.0:
+
+```yaml
+environment:
+ sdk: '>=2.4.0 <2.7.0'
+```
+
+In the package that has that pubspec, code like the following generates
+this diagnostic:
+
+{% prettify dart %}
+[!extension!] E on String {
+  void sayHello() {
+    print('Hello $this');
+  }
+}
+{% endprettify %}
+
+#### Common fixes
+
+If you don't need to support older versions of the SDK, then you can
+increase the SDK constraint to allow the syntax to be used:
+
+```yaml
+environment:
+  sdk: '>=2.6.0 <2.7.0'
+```
+
+If you need to support older versions of the SDK, then rewrite the code to
+not make use of extensions. The most common way to do this is to rewrite
+the members of the extension as top-level functions (or methods) that take
+the value that would have been bound to `this` as a parameter:
+
+{% prettify dart %}
+void sayHello(String s) {
+  print('Hello $s');
+}
+{% endprettify %}
+
+### sdk_version_is_expression_in_const_context
+
+_The use of an is expression in a constant context wasn't supported until
+version 2.3.2, but this code is required to be able to run on earlier versions._
+
+#### Description
+
+The analyzer produces this diagnostic when an is expression inside a
+[constant context](#constant-context) is found in code that has an SDK
+constraint whose lower bound is less than 2.3.2. Using an is expression in
+a [constant context](#constant-context) wasn't supported in earlier
+versions, so this code won't be able to run against earlier versions of the
+SDK.
+
+#### Example
+
+Here's an example of a pubspec that defines an SDK constraint with a lower
+bound of less than 2.3.2:
+
+```yaml
+environment:
+  sdk: '>=2.1.0 <2.4.0'
+```
+
+In the package that has that pubspec, code like the following generates
+this diagnostic:
+
+{% prettify dart %}
+const x = 4;
+const y = [!x is int!] ? 0 : 1;
+{% endprettify %}
+
+#### Common fixes
+
+If you don't need to support older versions of the SDK, then you can
+increase the SDK constraint to allow the expression to be used:
+
+```yaml
+environment:
+  sdk: '>=2.3.2 <2.4.0'
+```
+
+If you need to support older versions of the SDK, then either rewrite the
+code to not use the is operator, or, if that's not possible, change the
+code so that the is expression is not in a
+[constant context](#constant-context).:
+
+{% prettify dart %}
+const x = 4;
+var y = x is int ? 0 : 1;
+{% endprettify %}
+
 ### sdk_version_set_literal
 
 _Set literals weren't supported until version 2.2, but this code is required to
@@ -643,21 +1378,22 @@
 #### Description
 
 The analyzer produces this diagnostic when a set literal is found in code
-that has an SDK constraint whose lower bound is less than 2.2. Set literals
-weren't supported in earlier versions, so this code won't be able to run
-against earlier versions of the SDK.
+that has an SDK constraint whose lower bound is less than 2.2.0. Set
+literals weren't supported in earlier versions, so this code won't be able
+to run against earlier versions of the SDK.
 
 #### Example
 
-In a package that defines the SDK constraint (in the pubspec.yaml file),
-with a lower bound of less than 2.2. For example:
+Here's an example of a pubspec that defines an SDK constraint with a lower
+bound of less than 2.2.0:
 
 ```yaml
 environment:
   sdk: '>=2.1.0 <2.4.0'
 ```
 
-The following code generates this diagnostic:
+In the package that has that pubspec, code like the following produces this
+diagnostic:
 
 {% prettify dart %}
 var s = [!<int>{}!];
@@ -680,6 +1416,150 @@
 var s = new Set<int>();
 {% endprettify %}
 
+### sdk_version_ui_as_code
+
+_The for, if, and spread elements weren't supported until version 2.2.2, but
+this code is required to be able to run on earlier versions._
+
+#### Description
+
+The analyzer produces this diagnostic when a for, if, or spread element is
+found in code that has an SDK constraint whose lower bound is less than
+2.3.0. Using a for, if, or spread element wasn't supported in earlier
+versions, so this code won't be able to run against earlier versions of the
+SDK.
+
+#### Example
+
+Here's an example of a pubspec that defines an SDK constraint with a lower
+bound of less than 2.3.0:
+
+```yaml
+environment:
+  sdk: '>=2.2.0 <2.4.0'
+```
+
+In the package that has that pubspec, code like the following generates
+this diagnostic:
+
+{% prettify dart %}
+var digits = [[!for (int i = 0; i < 10; i++) i!]];
+{% endprettify %}
+
+#### Common fixes
+
+If you don't need to support older versions of the SDK, then you can
+increase the SDK constraint to allow the syntax to be used:
+
+```yaml
+environment:
+  sdk: '>=2.3.0 <2.4.0'
+```
+
+If you need to support older versions of the SDK, then rewrite the code to
+not make use of those elements:
+
+{% prettify dart %}
+var digits = _initializeDigits();
+
+List<int> _initializeDigits() {
+  var digits = <int>[];
+  for (int i = 0; i < 10; i++) {
+    digits.add(i);
+  }
+  return digits;
+}
+{% endprettify %}
+
+### sdk_version_ui_as_code_in_const_context
+
+_The if and spread elements weren't supported in constant expressions until
+version 2.5.0, but this code is required to be able to run on earlier versions._
+
+#### Description
+
+The analyzer produces this diagnostic when an if or spread element inside
+a [constant context](#constant-context) is found in code that has an
+SDK constraint whose lower bound is less than 2.5.0. Using an if or
+spread element inside a [constant context](#constant-context) wasn't
+supported in earlier versions, so this code won't be able to run against
+earlier versions of the SDK.
+
+#### Example
+
+Here's an example of a pubspec that defines an SDK constraint with a lower
+bound of less than 2.5.0:
+
+```yaml
+environment:
+  sdk: '>=2.4.0 <2.6.0'
+```
+
+In the package that has that pubspec, code like the following generates
+this diagnostic:
+
+{% prettify dart %}
+const a = [1, 2];
+const b = [[!...a!]];
+{% endprettify %}
+
+#### Common fixes
+
+If you don't need to support older versions of the SDK, then you can
+increase the SDK constraint to allow the syntax to be used:
+
+```yaml
+environment:
+  sdk: '>=2.5.0 <2.6.0'
+```
+
+If you need to support older versions of the SDK, then rewrite the code to
+not make use of those elements:
+
+{% prettify dart %}
+const a = [1, 2];
+const b = [1, 2];
+{% endprettify %}
+
+If that's not possible, change the code so that the element is not in a
+[constant context](#constant-context).:
+
+{% prettify dart %}
+const a = [1, 2];
+var b = [...a];
+{% endprettify %}
+
+### super_in_extension
+
+_The 'super' keyword can't be used in an extension because an extension doesn't
+have a superclass._
+
+#### Description
+
+The analyzer produces this diagnostic when a member declared inside an
+extension uses the `super` keyword . Extensions aren't classes and don't
+have superclasses, so the `super` keyword serves no purpose.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+extension E on Object {
+  String get displayString => [!super!].toString();
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove the `super` keyword :
+
+{% prettify dart %}
+extension E on Object {
+  String get displayString => toString();
+}
+{% endprettify %}
+
 ### type_argument_not_matching_bounds
 
 _'{0}' doesn't extend '{1}'._
@@ -726,9 +1606,7 @@
 {% prettify dart %}
 class Point {}
 
-void main() {
-  [!Piont!] p;
-}
+void f([!Piont!] p) {}
 {% endprettify %}
 
 #### Common fixes
@@ -740,14 +1618,293 @@
 {% prettify dart %}
 class Point {}
 
-void main() {
-  Point p;
-}
+void f(Point p) {}
 {% endprettify %}
 
 If the class is defined but isn't visible, then you probably need to add an
 import.
 
+### undefined_extension_getter
+
+_The getter '{0}' isn't defined for the extension '{1}'._
+
+#### Description
+
+The analyzer produces this diagnostic when an extension override is used to
+invoke a getter, but the getter isn't defined by the specified extension.
+The analyzer also produces this diagnostic when a static getter is
+referenced but isn't defined by the specified extension.
+
+#### Example
+
+The following code produces this diagnostic because the extension `E`
+doesn't declare an instance getter named `b`:
+
+{% prettify dart %}
+extension E on String {
+  String get a => 'a';
+}
+
+extension F on String {
+  String get b => 'b';
+}
+
+void f() {
+  E('c').[!b!];
+}
+{% endprettify %}
+
+The following code produces this diagnostic because the extension `E`
+doesn't declare a static getter named `a`:
+
+{% prettify dart %}
+extension E on String {}
+
+var x = E.[!a!];
+{% endprettify %}
+
+#### Common fixes
+
+If the name of the getter is incorrect, then change it to the name of an
+existing getter:
+
+{% prettify dart %}
+extension E on String {
+  String get a => 'a';
+}
+
+extension F on String {
+  String get b => 'b';
+}
+
+void f() {
+  E('c').a;
+}
+{% endprettify %}
+
+If the name of the getter is correct but the name of the extension is
+wrong, then change the name of the extension to the correct name:
+
+{% prettify dart %}
+extension E on String {
+  String get a => 'a';
+}
+
+extension F on String {
+  String get b => 'b';
+}
+
+void f() {
+  F('c').b;
+}
+{% endprettify %}
+
+If the name of the getter and extension are both correct, but the getter
+isn't defined, then define the getter:
+
+{% prettify dart %}
+extension E on String {
+  String get a => 'a';
+  String get b => 'z';
+}
+
+extension F on String {
+  String get b => 'b';
+}
+
+void f() {
+  E('c').b;
+}
+{% endprettify %}
+
+### undefined_extension_method
+
+_The method '{0}' isn't defined for the extension '{1}'._
+
+#### Description
+
+The analyzer produces this diagnostic when an extension override is used to
+invoke a method, but the method isn't defined by the specified extension.
+The analyzer also produces this diagnostic when a static method is
+referenced but isn't defined by the specified extension.
+
+#### Example
+
+The following code produces this diagnostic because the extension `E`
+doesn't declare an instance method named `b`:
+
+{% prettify dart %}
+extension E on String {
+  String a() => 'a';
+}
+
+extension F on String {
+  String b() => 'b';
+}
+
+void f() {
+  E('c').[!b!]();
+}
+{% endprettify %}
+
+The following code produces this diagnostic because the extension `E`
+doesn't declare a static method named `a`:
+
+{% prettify dart %}
+extension E on String {}
+
+var x = E.[!a!]();
+{% endprettify %}
+
+#### Common fixes
+
+If the name of the method is incorrect, then change it to the name of an
+existing method:
+
+{% prettify dart %}
+extension E on String {
+  String a() => 'a';
+}
+
+extension F on String {
+  String b() => 'b';
+}
+
+void f() {
+  E('c').a();
+}
+{% endprettify %}
+
+If the name of the method is correct, but the name of the extension is
+wrong, then change the name of the extension to the correct name:
+
+{% prettify dart %}
+extension E on String {
+  String a() => 'a';
+}
+
+extension F on String {
+  String b() => 'b';
+}
+
+void f() {
+  F('c').b();
+}
+{% endprettify %}
+
+If the name of the method and extension are both correct, but the method
+isn't defined, then define the method:
+
+{% prettify dart %}
+extension E on String {
+  String a() => 'a';
+  String b() => 'z';
+}
+
+extension F on String {
+  String b() => 'b';
+}
+
+void f() {
+  E('c').b();
+}
+{% endprettify %}
+
+### undefined_extension_setter
+
+_The setter '{0}' isn't defined for the extension '{1}'._
+
+#### Description
+
+The analyzer produces this diagnostic when an extension override is used to
+invoke a setter, but the setter isn't defined by the specified extension.
+The analyzer also produces this diagnostic when a static setter is
+referenced but isn't defined by the specified extension.
+
+#### Example
+
+The following code produces this diagnostic because the extension `E`
+doesn't declare an instance setter named `b`:
+
+{% prettify dart %}
+extension E on String {
+  set a(String v) {}
+}
+
+extension F on String {
+  set b(String v) {}
+}
+
+void f() {
+  E('c').[!b!] = 'd';
+}
+{% endprettify %}
+
+The following code produces this diagnostic because the extension `E`
+doesn't declare a static setter named `a`:
+
+{% prettify dart %}
+extension E on String {}
+
+void f() {
+  E.[!a!] = 3;
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the name of the setter is incorrect, then change it to the name of an
+existing setter:
+
+{% prettify dart %}
+extension E on String {
+  set a(String v) {}
+}
+
+extension F on String {
+  set b(String v) {}
+}
+
+void f() {
+  E('c').a = 'd';
+}
+{% endprettify %}
+
+If the name of the setter is correct, but the name of the extension is
+wrong, then change the name of the extension to the correct name:
+
+{% prettify dart %}
+extension E on String {
+  set a(String v) {}
+}
+
+extension F on String {
+  set b(String v) {}
+}
+
+void f() {
+  F('c').b = 'd';
+}
+{% endprettify %}
+
+If the name of the setter and extension are both correct, but the setter
+isn't defined, then define the setter:
+
+{% prettify dart %}
+extension E on String {
+  set a(String v) {}
+  set b(String v) {}
+}
+
+extension F on String {
+  set b(String v) {}
+}
+
+void f() {
+  E('c').b = 'd';
+}
+{% endprettify %}
+
 ### undefined_function
 
 _The function '{0}' isn't defined._
@@ -805,7 +1962,7 @@
 int f(String s) => s.[!len!];
 {% endprettify %}
 
-#### Common fix
+#### Common fixes
 
 If the identifier isn't defined, then either define it or replace it with
 the name of a getter that is defined. The example above can be corrected by
@@ -864,7 +2021,7 @@
 int f(List<int> l) => l.[!removeMiddle!]();
 {% endprettify %}
 
-#### Common fix
+#### Common fixes
 
 If the identifier isn't defined, then either define it or replace it with
 the name of a method that is defined. The example above can be corrected by
@@ -881,7 +2038,7 @@
 #### Description
 
 The analyzer produces this diagnostic when a method or function invocation
-has a named argument, but the method or function being invoked doesn’t
+has a named argument, but the method or function being invoked doesn't
 define a parameter with the same name.
 
 #### Example
@@ -957,31 +2114,25 @@
 The following code produces this diagnostic:
 
 {% prettify dart %}
-class Point {
-  int x;
-  int y;
-  Point(this.x, this.y);
-  void shiftBy(Point other) {
-    this.x += other.x;
-    this.[!z!] += other.y;
+class C {
+  int x = 0;
+  void m(int y) {
+    this.[!z!] = y;
   }
 }
 {% endprettify %}
 
-#### Common fix
+#### Common fixes
 
 If the identifier isn't defined, then either define it or replace it with
 the name of a setter that is defined. The example above can be corrected by
 fixing the spelling of the setter:
 
 {% prettify dart %}
-class Point {
-  int x;
-  int y;
-  Point(this.x, this.y);
-  void shiftBy(Point other) {
-    this.x += other.x;
-    this.y += other.y;
+class C {
+  int x = 0;
+  void m(int y) {
+    this.x = y;
   }
 }
 {% endprettify %}
diff --git a/pkg/analyzer/tool/diagnostics/generate.dart b/pkg/analyzer/tool/diagnostics/generate.dart
index 36b166e..7f51a0d 100644
--- a/pkg/analyzer/tool/diagnostics/generate.dart
+++ b/pkg/analyzer/tool/diagnostics/generate.dart
@@ -17,36 +17,84 @@
 /// Generate the file `diagnostics.md` based on the documentation associated
 /// with the declarations of the error codes.
 void main() async {
-  Context pathContext = PhysicalResourceProvider.INSTANCE.pathContext;
-  String packageRoot = pathContext.normalize(package_root.packageRoot);
-  String analyzerPath = pathContext.join(packageRoot, 'analyzer');
-  List<String> docPaths = [
-    pathContext.join(
-        analyzerPath, 'lib', 'src', 'dart', 'error', 'hint_codes.dart'),
-    pathContext.join(analyzerPath, 'lib', 'src', 'error', 'codes.dart'),
-  ];
-  String outputPath =
-      pathContext.join(analyzerPath, 'tool', 'diagnostics', 'diagnostics.md');
-
-  IOSink sink = File(outputPath).openWrite();
-  DocumentationGenerator generator = DocumentationGenerator(docPaths);
+  IOSink sink = File(computeOutputPath()).openWrite();
+  DocumentationGenerator generator = DocumentationGenerator(computeCodePaths());
   generator.writeDocumentation(sink);
   await sink.flush();
   await sink.close();
 }
 
+/// Compute a list of the code paths for the files containing diagnostics that
+/// have been documented.
+List<CodePath> computeCodePaths() {
+  Context pathContext = PhysicalResourceProvider.INSTANCE.pathContext;
+  String packageRoot = pathContext.normalize(package_root.packageRoot);
+  String analyzerPath = pathContext.join(packageRoot, 'analyzer');
+  return CodePath.from([
+    [analyzerPath, 'lib', 'src', 'dart', 'error', 'hint_codes.dart'],
+    [analyzerPath, 'lib', 'src', 'dart', 'error', 'syntactic_errors.dart'],
+    [analyzerPath, 'lib', 'src', 'error', 'codes.dart'],
+  ], [
+    null,
+    [analyzerPath, 'lib', 'src', 'dart', 'error', 'syntactic_errors.g.dart'],
+    null,
+  ]);
+}
+
+/// Compute the path to the file into which documentation is being generated.
+String computeOutputPath() {
+  Context pathContext = PhysicalResourceProvider.INSTANCE.pathContext;
+  String packageRoot = pathContext.normalize(package_root.packageRoot);
+  String analyzerPath = pathContext.join(packageRoot, 'analyzer');
+  return pathContext.join(
+      analyzerPath, 'tool', 'diagnostics', 'diagnostics.md');
+}
+
+/// A representation of the paths to the documentation and declaration of a set
+/// of diagnostic codes.
+class CodePath {
+  /// The path to the file containing the declarations of the diagnostic codes
+  /// that might have documentation associated with them.
+  final String documentationPath;
+
+  /// The path to the file containing the generated definition of the diagnostic
+  /// codes that include the message, or `null` if the
+  final String declarationPath;
+
+  /// Initialize a newly created code path from the [documentationPath] and
+  /// [declarationPath].
+  CodePath(this.documentationPath, this.declarationPath);
+
+  /// Return a list of code paths computed by joining the path segments in the
+  /// corresponding lists from [documentationPaths] and [declarationPaths].
+  static List<CodePath> from(List<List<String>> documentationPaths,
+      List<List<String>> declarationPaths) {
+    Context pathContext = PhysicalResourceProvider.INSTANCE.pathContext;
+    List<CodePath> paths = [];
+    for (int i = 0; i < documentationPaths.length; i++) {
+      String docPath = pathContext.joinAll(documentationPaths[i]);
+      String declPath = null;
+      if (declarationPaths[i] != null) {
+        declPath = pathContext.joinAll(declarationPaths[i]);
+      }
+      paths.add(CodePath(docPath, declPath));
+    }
+    return paths;
+  }
+}
+
 /// A class used to generate diagnostic documentation.
 class DocumentationGenerator {
   /// The absolute paths of the files containing the declarations of the error
   /// codes.
-  final List<String> docPaths;
+  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 = {};
 
   /// Initialize a newly created documentation generator.
-  DocumentationGenerator(this.docPaths) {
+  DocumentationGenerator(this.codePaths) {
     _extractAllDocs();
   }
 
@@ -66,11 +114,30 @@
   /// Extract documentation from all of the files containing the definitions of
   /// diagnostics.
   void _extractAllDocs() {
+    List<String> includedPaths = [];
+    for (CodePath codePath in codePaths) {
+      includedPaths.add(codePath.documentationPath);
+      if (codePath.declarationPath != null) {
+        includedPaths.add(codePath.declarationPath);
+      }
+    }
     AnalysisContextCollection collection = new AnalysisContextCollection(
-        includedPaths: docPaths,
+        includedPaths: includedPaths,
         resourceProvider: PhysicalResourceProvider.INSTANCE);
-    for (String docPath in docPaths) {
-      _extractDocs(_parse(collection, docPath));
+    for (CodePath codePath in codePaths) {
+      String docPath = codePath.documentationPath;
+      String declPath = codePath.declarationPath;
+      if (declPath == null) {
+        _extractDocs(_parse(collection, docPath), null);
+      } else {
+        File file = File(declPath);
+        if (file.existsSync()) {
+          _extractDocs(
+              _parse(collection, docPath), _parse(collection, declPath));
+        } else {
+          _extractDocs(_parse(collection, docPath), null);
+        }
+      }
     }
   }
 
@@ -86,6 +153,8 @@
       String lexeme = comments.lexeme;
       if (lexeme.startsWith('// TODO')) {
         break;
+      } else if (lexeme.startsWith('// %')) {
+        // Ignore lines containing directives for testing support.
       } else if (lexeme.startsWith('// ')) {
         String trimmedLine = lexeme.substring(3);
         if (trimmedLine == '```dart') {
@@ -113,8 +182,9 @@
   }
 
   /// Extract documentation from the file that was parsed to produce the given
-  /// [result].
-  void _extractDocs(ParsedUnitResult result) {
+  /// [result]. If a [generatedResult] is provided, then the messages might be
+  /// in the file parsed to produce the result.
+  void _extractDocs(ParsedUnitResult result, ParsedUnitResult generatedResult) {
     CompilationUnit unit = result.unit;
     for (CompilationUnitMember declaration in unit.declarations) {
       if (declaration is ClassDeclaration) {
@@ -128,10 +198,7 @@
                 throw StateError('Duplicate diagnostic code');
               }
               String message =
-                  ((variable.initializer as InstanceCreationExpression)
-                          .argumentList
-                          .arguments[1] as StringLiteral)
-                      .stringValue;
+                  _extractMessage(variable.initializer, generatedResult);
               docs = [
                 '### ${variableName.toLowerCase()}',
                 '',
@@ -147,6 +214,40 @@
     }
   }
 
+  /// 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);
+      }
+    }
+    throw StateError(
+        'Cannot extract a message from a ${expression.runtimeType}');
+  }
+
+  /// Return the declaration of the top-level variable with the [name] in the
+  /// compilation unit, or `null` if there is no such variable.
+  VariableDeclaration _findVariable(String name, CompilationUnit unit) {
+    for (CompilationUnitMember member in unit.declarations) {
+      if (member is TopLevelVariableDeclaration) {
+        for (VariableDeclaration variable in member.variables.variables) {
+          if (variable.name.name == name) {
+            return variable;
+          }
+        }
+      }
+    }
+    return null;
+  }
+
   /// Use the analysis context [collection] to parse the file at the given
   /// [path] and return the result.
   ParsedUnitResult _parse(AnalysisContextCollection collection, String path) {
diff --git a/pkg/analyzer_cli/lib/src/analyzer_impl.dart b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
index 2d88a91..c5e1bc2 100644
--- a/pkg/analyzer_cli/lib/src/analyzer_impl.dart
+++ b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
@@ -11,7 +11,7 @@
 import 'package:analyzer/exception/exception.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' hide AnalysisResult;
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index be6d5f0..a4363fc 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -399,6 +399,16 @@
           if (directive is PartDirective) {
             var partUri = directive.uri.stringValue;
             var partSource = sourceFactory.resolveUri(librarySource, partUri);
+
+            // Add empty synthetic units for unresolved `part` URIs.
+            if (partSource == null) {
+              var unit = analysisDriver.fsState.unresolvedFile.parse();
+              inputUnits.add(
+                summary2.LinkInputUnit(partUri, null, true, unit),
+              );
+              continue;
+            }
+
             var partPath = partSource.fullName;
             var partParseResult = inputParsedUnitResults[partPath];
             if (partParseResult == null) {
diff --git a/pkg/analyzer_cli/lib/src/error_severity.dart b/pkg/analyzer_cli/lib/src/error_severity.dart
index e43d77c..198ff9a 100644
--- a/pkg/analyzer_cli/lib/src/error_severity.dart
+++ b/pkg/analyzer_cli/lib/src/error_severity.dart
@@ -5,7 +5,7 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/source/error_processor.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer_cli/src/options.dart';
 
 /// Compute the severity of the error; however:
diff --git a/pkg/analyzer_cli/test/driver_test.dart b/pkg/analyzer_cli/test/driver_test.dart
index 02d79d9..705be26 100644
--- a/pkg/analyzer_cli/test/driver_test.dart
+++ b/pkg/analyzer_cli/test/driver_test.dart
@@ -605,6 +605,34 @@
     });
   }
 
+  test_buildLinked_invalidPartUri() async {
+    await withTempDirAsync((tempDir) async {
+      var aDart = path.join(tempDir, 'a.dart');
+
+      var aUri = 'package:aaa/a.dart';
+
+      var aSum = path.join(tempDir, 'a.sum');
+
+      new File(aDart).writeAsStringSync('''
+part '[invalid]';
+''');
+
+      await _doDrive(aDart,
+          uri: aUri, additionalArgs: ['--build-summary-output=$aSum']);
+      expect(exitCode, ErrorSeverity.ERROR.ordinal);
+      var bytes = new File(aSum).readAsBytesSync();
+      var bundle = new PackageBundle.fromBuffer(bytes);
+      if (AnalysisDriver.useSummary2) {
+        var bundle2 = bundle.bundle2;
+        expect(_linkedLibraryUriList(bundle2), [aUri]);
+        expect(_linkedLibraryUnitUriList(bundle2, aUri), [aUri, '']);
+      } else {
+        expect(bundle.unlinkedUnitUris, equals([aUri]));
+        expect(bundle.linkedLibraryUris, equals([aUri]));
+      }
+    });
+  }
+
   test_buildSuppressExitCode_fail_whenFileNotFound() async {
     await _doDrive(path.join('data', 'non_existent_file.dart'),
         additionalArgs: ['--build-suppress-exit-code']);
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
index 6e1993b..d4a9061 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
@@ -18,7 +18,6 @@
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
     hide Element, ElementKind;
 import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_core.dart';
-import 'package:analyzer_plugin/src/utilities/change_builder/dart/import_library_element.dart';
 import 'package:analyzer_plugin/src/utilities/string_utilities.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
@@ -26,7 +25,6 @@
 import 'package:analyzer_plugin/utilities/range_factory.dart';
 import 'package:charcode/ascii.dart';
 import 'package:dart_style/dart_style.dart';
-import 'package:meta/meta.dart';
 
 /**
  * A [ChangeBuilder] used to build changes in Dart files.
@@ -1291,34 +1289,19 @@
   }
 
   @override
-  ImportLibraryElementResult importLibraryElement({
-    @required ResolvedLibraryResult targetLibrary,
-    @required String targetPath,
-    @required int targetOffset,
-    @required LibraryElement requestedLibrary,
-    @required Element requestedElement,
-  }) {
-    if (librariesToImport.isNotEmpty ||
-        librariesToRelativelyImport.isNotEmpty) {
-      throw StateError('Only one library can be safely imported.');
+  ImportLibraryElementResult importLibraryElement(Uri uri) {
+    if (resolvedUnit.libraryElement.source.uri == uri) {
+      return ImportLibraryElementResultImpl(null);
     }
 
-    var request = importLibraryElementImpl(
-      targetResolvedLibrary: targetLibrary,
-      targetPath: targetPath,
-      targetOffset: targetOffset,
-      requestedLibrary: requestedLibrary,
-      requestedElement: requestedElement,
-    );
-
-    var prefix = request.prefix;
-    if (request.uri != null) {
-      var uriText = _getLibraryUriText(request.uri);
-      (libraryChangeBuilder ?? this).librariesToImport[request.uri] =
-          _LibraryToImport(uriText, prefix);
+    for (var import in resolvedUnit.libraryElement.imports) {
+      if (import.importedLibrary.source.uri == uri) {
+        return ImportLibraryElementResultImpl(import.prefix?.name);
+      }
     }
 
-    return ImportLibraryElementResultImpl(prefix);
+    importLibrary(uri);
+    return ImportLibraryElementResultImpl(null);
   }
 
   String importLibraryWithRelativeUri(String uriText, [String prefix = null]) {
@@ -1328,23 +1311,16 @@
   @override
   void replaceTypeWithFuture(
       TypeAnnotation typeAnnotation, TypeProvider typeProvider) {
-    InterfaceType futureType = typeProvider.futureType;
     //
     // Check whether the type needs to be replaced.
     //
     DartType type = typeAnnotation?.type;
-    if (type == null ||
-        type.isDynamic ||
-        type is InterfaceType && type.element == futureType.element) {
+    if (type == null || type.isDynamic || type.isDartAsyncFuture) {
       return;
     }
-    // TODO(brianwilkerson) Unconditionally execute the body of the 'if' when
-    // Future<void> is fully supported.
-    if (!type.isVoid) {
-      futureType = futureType.instantiate(<DartType>[type]);
-    }
-    // prepare code for the types
+
     addReplacement(range.node(typeAnnotation), (EditBuilder builder) {
+      var futureType = typeProvider.futureType2(type);
       if (!(builder as DartEditBuilder).writeType(futureType)) {
         builder.write('void');
       }
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/import_library_element.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/import_library_element.dart
deleted file mode 100644
index f135dd8..0000000
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/import_library_element.dart
+++ /dev/null
@@ -1,193 +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/dart/analysis/results.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/visitor.dart';
-import 'package:analyzer_plugin/src/utilities/change_builder/dart/syntactic_scope.dart';
-import 'package:meta/meta.dart';
-
-ImportLibraryRequest importLibraryElementImpl({
-  @required ResolvedLibraryResult targetResolvedLibrary,
-  @required String targetPath,
-  @required int targetOffset,
-  @required LibraryElement requestedLibrary,
-  @required Element requestedElement,
-}) {
-  var targetLibrary = targetResolvedLibrary.element;
-
-  var requestedLibraryUri = requestedLibrary.source.uri;
-  var requestedElementUri = requestedElement.librarySource.uri;
-  var requestedName = requestedElement.displayName;
-
-  // If the element is defined in this library, then no prefix needed.
-  if (targetLibrary == requestedElement.library) {
-    return ImportLibraryRequest(null, null);
-  }
-
-  var requestedElements = requestedLibrary.exportNamespace.definedNames;
-  _removeEntriesForDynamicAndNever(requestedElements);
-
-  // Find URIs of all libraries that import the requested name into the target.
-  var unprefixedNameUriSet = Set<Uri>();
-  for (var import in targetLibrary.imports) {
-    var definedNames = import.namespace.definedNames;
-    if (import.prefix == null) {
-      var element = definedNames[requestedName];
-      if (element != null) {
-        unprefixedNameUriSet.add(element.librarySource.uri);
-      }
-    }
-  }
-
-  // Find names that will be shadowed by a new unprefixed import.
-  var collector = NotSyntacticScopeReferencedNamesCollector(
-    targetResolvedLibrary.element,
-    requestedElements.keys.toSet(),
-  );
-  for (var resolvedUnit in targetResolvedLibrary.units) {
-    resolvedUnit.unit.accept(collector);
-  }
-
-  // Find names that will shadow unprefixed references.
-  var scopeNames = Set<String>();
-  targetLibrary.accept(_TopLevelNamesCollector(scopeNames));
-  for (var resolvedUnit in targetResolvedLibrary.units) {
-    if (resolvedUnit.path == targetPath) {
-      resolvedUnit.unit.accept(
-        SyntacticScopeNamesCollector(scopeNames, targetOffset),
-      );
-    }
-  }
-
-  var canUseUnprefixedImport = true;
-
-  // If a name is inherited, it will be shadowed by a new unprefixed import.
-  if (collector.inheritedNames.isNotEmpty) {
-    canUseUnprefixedImport = false;
-  }
-
-  // If a name is imported, and it is not the same as the one from the
-  // requested library, then a new unprefixed import will cause ambiguity.
-  for (var name in collector.importedNames.keys) {
-    var importedUri = collector.importedNames[name];
-    var requestedUri = requestedElements[name]?.librarySource?.uri;
-    if (requestedUri != importedUri) {
-      canUseUnprefixedImport = false;
-      break;
-    }
-  }
-
-  // If syntactic scope at the offset has the requested name, then the name
-  // from an unprefixed import will be shadowed.
-  if (scopeNames.contains(requestedName)) {
-    canUseUnprefixedImport = false;
-  }
-
-  // If the requested name is ambiguous from existing unprefixed imports,
-  // or is not the same element as the one from the requested library, then
-  // we cannot use unprefixed import.
-  if (unprefixedNameUriSet.isNotEmpty) {
-    if (unprefixedNameUriSet.length > 1 ||
-        unprefixedNameUriSet.first != requestedElementUri) {
-      canUseUnprefixedImport = false;
-    }
-  }
-
-  // Find import prefixes with which the name is ambiguous.
-  var ambiguousWithImportPrefixes = Set<String>();
-  for (var import in targetLibrary.imports) {
-    var definedNames = import.namespace.definedNames;
-    if (import.prefix != null) {
-      var prefix = import.prefix.name;
-      var prefixedName = '$prefix.$requestedName';
-      var importedElement = definedNames[prefixedName];
-      if (importedElement != null &&
-          importedElement.librarySource.uri != requestedElementUri) {
-        ambiguousWithImportPrefixes.add(prefix);
-      }
-    }
-  }
-
-  // Check for existing imports of the requested library.
-  for (var import in targetLibrary.imports) {
-    if (import.importedLibrary?.source?.uri == requestedLibraryUri) {
-      var importedNames = import.namespace.definedNames;
-      if (import.prefix == null) {
-        if (canUseUnprefixedImport &&
-            importedNames.containsKey(requestedName)) {
-          return ImportLibraryRequest(null, null);
-        }
-      } else {
-        var prefix = import.prefix.name;
-        var prefixedName = '$prefix.$requestedName';
-        if (importedNames.containsKey(prefixedName) &&
-            !ambiguousWithImportPrefixes.contains(prefix)) {
-          return ImportLibraryRequest(null, prefix);
-        }
-      }
-    }
-  }
-
-  // If the name cannot be used without import prefix, generate one.
-  String prefix;
-  if (!canUseUnprefixedImport) {
-    prefix = 'prefix';
-    for (var index = 0;; index++) {
-      prefix = 'prefix$index';
-      if (!collector.referencedNames.contains(prefix)) {
-        break;
-      }
-    }
-  }
-
-  return ImportLibraryRequest(requestedLibraryUri, prefix);
-}
-
-/// The types `dynamic` and `Never` are part of 'dart:core', but have no
-/// library.
-void _removeEntriesForDynamicAndNever(Map<String, Element> requestedElements) {
-  requestedElements.removeWhere((_, element) {
-    if (element.librarySource == null) {
-      assert(
-          element.displayName == 'dynamic' || element.displayName == 'Never');
-      return true;
-    }
-    return false;
-  });
-}
-
-/// Information about a library to import.
-class ImportLibraryRequest {
-  /// The URI of the library to import, or `null` if the requested library is
-  /// already imported, with the [prefix], so no new import is required.
-  final Uri uri;
-
-  /// The prefix with which ths requested library is already imported,
-  /// or should be imported, or `null` is no prefix is necessary.
-  final String prefix;
-
-  ImportLibraryRequest(this.uri, this.prefix);
-}
-
-/// Element visitor that collects names of top-level elements.
-class _TopLevelNamesCollector extends GeneralizingElementVisitor<void> {
-  final Set<String> names;
-
-  _TopLevelNamesCollector(this.names);
-
-  @override
-  void visitElement(Element element) {
-    if (element is LibraryElement || element is CompilationUnitElement) {
-      super.visitElement(element);
-    } else if (element is ImportElement) {
-      var prefix = element.prefix?.displayName;
-      if (prefix != null) {
-        names.add(prefix);
-      }
-    } else if (element.enclosingElement is CompilationUnitElement) {
-      names.add(element.displayName);
-    }
-  }
-}
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/syntactic_scope.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/syntactic_scope.dart
deleted file mode 100644
index 959d1f0..0000000
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/syntactic_scope.dart
+++ /dev/null
@@ -1,349 +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/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/dart/element/element.dart';
-
-/// AST visitor that collects names that are referenced, but the target element
-/// is not defined in the syntactic scope of the reference.  Resolution of
-/// such names will change when the import scope of the library changes.
-class NotSyntacticScopeReferencedNamesCollector
-    extends GeneralizingAstVisitor<void> {
-  /// The library that contains resolved AST(s) being visited.
-  final LibraryElement enclosingLibraryElement;
-
-  /// The names that we need to check.
-  final Set<String> interestingNames;
-
-  /// All the referenced unqualified names.
-  final Set<String> referencedNames = Set<String>();
-
-  /// The subset of [interestingNames] that are resolved to a top-level
-  /// element that is not in the syntactic scope of the reference, and the
-  /// library [Uri] is the value in the mapping.
-  final Map<String, Uri> importedNames = {};
-
-  /// The subset of [interestingNames] that are resolved to inherited names.
-  final Set<String> inheritedNames = Set<String>();
-
-  Element enclosingUnitMemberElement;
-
-  NotSyntacticScopeReferencedNamesCollector(
-    this.enclosingLibraryElement,
-    this.interestingNames,
-  );
-
-  @override
-  void visitCombinator(Combinator node) {}
-
-  @override
-  void visitCompilationUnitMember(CompilationUnitMember node) {
-    enclosingUnitMemberElement = node.declaredElement;
-    super.visitCompilationUnitMember(node);
-    enclosingUnitMemberElement = null;
-  }
-
-  @override
-  void visitConstructorName(ConstructorName node) {
-    node.type.accept(this);
-  }
-
-  @override
-  void visitPrefixedIdentifier(PrefixedIdentifier node) {
-    node.prefix.accept(this);
-  }
-
-  @override
-  void visitSimpleIdentifier(SimpleIdentifier node) {
-    var name = node.name;
-    referencedNames.add(name);
-
-    if (node.isQualified) return;
-    if (!interestingNames.contains(name)) return;
-
-    var element = node.staticElement;
-    if (element == null) return;
-
-    if (_inSyntacticScope(element)) return;
-
-    if (element.enclosingElement is CompilationUnitElement) {
-      importedNames[name] = element.librarySource.uri;
-    } else {
-      inheritedNames.add(name);
-    }
-  }
-
-  bool _inSyntacticScope(Element element) {
-    if (element.enclosingElement is CompilationUnitElement &&
-        element.enclosingElement.enclosingElement == enclosingLibraryElement) {
-      return true;
-    }
-
-    while (element != null) {
-      if (element == enclosingUnitMemberElement) return true;
-      element = element.enclosingElement;
-    }
-    return false;
-  }
-}
-
-/// AST visitor that collects syntactic scope names visible at the [offset].
-///
-/// The AST does not need to be resolved.
-class SyntacticScopeNamesCollector extends RecursiveAstVisitor<void> {
-  final Set<String> names;
-  final int offset;
-
-  SyntacticScopeNamesCollector(this.names, this.offset);
-
-  @override
-  void visitBlock(Block node) {
-    if (!_isCoveredBy(node)) return;
-
-    super.visitBlock(node);
-
-    for (var statement in node.statements) {
-      if (statement is FunctionDeclarationStatement) {
-        _addName(statement.functionDeclaration.name);
-      } else if (statement is VariableDeclarationStatement) {
-        _addVariables(statement.variables);
-      }
-    }
-  }
-
-  @override
-  void visitCatchClause(CatchClause node) {
-    if (!_isCoveredBy(node)) return;
-
-    if (node.exceptionParameter != null) {
-      _addName(node.exceptionParameter);
-    }
-
-    if (node.stackTraceParameter != null) {
-      _addName(node.stackTraceParameter);
-    }
-
-    node.body.accept(this);
-  }
-
-  @override
-  void visitClassDeclaration(ClassDeclaration node) {
-    if (!_isCoveredBy(node)) return;
-
-    _addTypeParameters(node.typeParameters);
-    _visitClassOrMixinMembers(node);
-  }
-
-  @override
-  void visitClassTypeAlias(ClassTypeAlias node) {
-    if (!_isCoveredBy(node)) return;
-    _addTypeParameters(node.typeParameters);
-  }
-
-  @override
-  void visitConstructorDeclaration(ConstructorDeclaration node) {
-    if (!_isCoveredBy(node)) return;
-
-    _addFormalParameters(node.parameters);
-
-    node.body.accept(this);
-  }
-
-  @override
-  void visitFieldDeclaration(FieldDeclaration node) {
-    var variableList = node.fields;
-
-    // `Foo^ Foo bar() {}` is recovered as `Foo Foo; bar() {}`, i.e. the
-    // return type of `bar()` gets associated with a new variable declaration.
-    if (node.semicolon.isSynthetic) {
-      if (variableList.variables.length == 1) {
-        var name = variableList.variables[0].name.name;
-        names.remove(name);
-      }
-    }
-
-    super.visitFieldDeclaration(node);
-  }
-
-  @override
-  void visitForElement(ForElement node) {
-    if (!_isCoveredBy(node)) return;
-
-    _addForLoopParts(node.forLoopParts, node.body);
-
-    super.visitForElement(node);
-  }
-
-  @override
-  void visitForStatement(ForStatement node) {
-    if (!_isCoveredBy(node)) return;
-
-    _addForLoopParts(node.forLoopParts, node.body);
-
-    super.visitForStatement(node);
-  }
-
-  @override
-  void visitFunctionDeclaration(FunctionDeclaration node) {
-    if (!_isCoveredBy(node)) return;
-
-    var function = node.functionExpression;
-    _addTypeParameters(function.typeParameters);
-
-    if (function.parameters != null && offset > function.parameters.offset) {
-      _addFormalParameters(function.parameters);
-    }
-
-    function.body.accept(this);
-  }
-
-  @override
-  void visitFunctionTypeAlias(FunctionTypeAlias node) {
-    if (!_isCoveredBy(node)) return;
-
-    _addTypeParameters(node.typeParameters);
-
-    if (offset > node.parameters.offset) {
-      _addFormalParameters(node.parameters);
-    }
-  }
-
-  @override
-  void visitGenericFunctionType(GenericFunctionType node) {
-    if (!_isCoveredBy(node)) return;
-
-    _addTypeParameters(node.typeParameters);
-
-    if (offset > node.parameters.offset) {
-      _addFormalParameters(node.parameters);
-    }
-  }
-
-  @override
-  void visitGenericTypeAlias(GenericTypeAlias node) {
-    if (!_isCoveredBy(node)) return;
-
-    _addTypeParameters(node.typeParameters);
-
-    node.functionType.accept(this);
-  }
-
-  @override
-  void visitMethodDeclaration(MethodDeclaration node) {
-    if (!_isCoveredBy(node)) return;
-
-    _addTypeParameters(node.typeParameters);
-
-    if (node.parameters != null && offset > node.parameters.offset) {
-      _addFormalParameters(node.parameters);
-    }
-
-    node.body.accept(this);
-  }
-
-  @override
-  void visitMixinDeclaration(MixinDeclaration node) {
-    if (!_isCoveredBy(node)) return;
-
-    _addTypeParameters(node.typeParameters);
-    _visitClassOrMixinMembers(node);
-  }
-
-  @override
-  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
-    // `TypeName^` is recovered as `<noType> TypeName;`, remove the name.
-    var variableList = node.variables;
-    if (variableList.keyword == null && variableList.type == null) {
-      for (var variable in variableList.variables) {
-        names.remove(variable.name.name);
-      }
-      return;
-    }
-
-    // `Foo^ Foo bar() {}` is recovered as `Foo Foo; bar() {}`, i.e. the
-    // return type of `bar()` gets associated with a new variable declaration.
-    if (node.semicolon.isSynthetic) {
-      if (variableList.variables.length == 1) {
-        var name = variableList.variables[0].name.name;
-        names.remove(name);
-      }
-    }
-
-    super.visitTopLevelVariableDeclaration(node);
-  }
-
-  void _addForLoopParts(ForLoopParts forLoopParts, AstNode body) {
-    if (forLoopParts is ForEachPartsWithDeclaration) {
-      if (_isCoveredBy(body)) {
-        _addName(forLoopParts.loopVariable.identifier);
-      }
-    } else if (forLoopParts is ForPartsWithDeclarations) {
-      _addVariables(forLoopParts.variables);
-    }
-  }
-
-  void _addFormalParameter(FormalParameter parameter) {
-    if (parameter is DefaultFormalParameter) {
-      _addFormalParameter(parameter.parameter);
-    } else if (parameter is FieldFormalParameter) {
-      _addName(parameter.identifier);
-    } else if (parameter is FunctionTypedFormalParameter) {
-      _addName(parameter.identifier);
-      var parameters = parameter.parameters;
-      if (parameters != null && _isCoveredBy(parameters)) {
-        _addFormalParameters(parameters);
-      }
-    } else if (parameter is SimpleFormalParameter) {
-      _addName(parameter.identifier);
-    } else {
-      throw UnimplementedError('(${parameter.runtimeType}) $parameter');
-    }
-  }
-
-  void _addFormalParameters(FormalParameterList parameterList) {
-    for (var parameter in parameterList.parameters) {
-      _addFormalParameter(parameter);
-    }
-  }
-
-  void _addName(SimpleIdentifier node) {
-    if (node == null) return;
-    if (node.offset <= offset && offset <= node.end) return;
-
-    names.add(node.name);
-  }
-
-  void _addTypeParameters(TypeParameterList typeParameterList) {
-    if (typeParameterList == null) return;
-
-    for (var typeParameter in typeParameterList.typeParameters) {
-      _addName(typeParameter.name);
-    }
-  }
-
-  void _addVariables(VariableDeclarationList variableList) {
-    for (var field in variableList.variables) {
-      _addName(field.name);
-    }
-  }
-
-  bool _isCoveredBy(AstNode node) {
-    return node.offset < offset && offset < node.end;
-  }
-
-  void _visitClassOrMixinMembers(ClassOrMixinDeclaration node) {
-    if (offset < node.leftBracket.offset) return;
-
-    for (var member in node.members) {
-      if (member is FieldDeclaration) {
-        _addVariables(member.fields);
-      } else if (member is MethodDeclaration) {
-        _addName(member.name);
-      }
-    }
-
-    node.members.accept(this);
-  }
-}
diff --git a/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart b/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart
index 87c832c..d0a3556 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart
@@ -29,6 +29,8 @@
 
   void declaredEnum(EnumDeclaration declaration) {}
 
+  void declaredExtension(ExtensionDeclaration declaration);
+
   void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl);
 
   void declaredFunction(FunctionDeclaration declaration);
@@ -107,6 +109,9 @@
         _visitTypeParameters(declaration, declaration.typeParameters);
       } else if (declaration is EnumDeclaration) {
         declaredEnum(declaration);
+      } else if (declaration is ExtensionDeclaration) {
+        declaredExtension(declaration);
+        _visitTypeParameters(declaration, declaration.typeParameters);
       } else if (declaration is FunctionDeclaration) {
         declaredFunction(declaration);
         _visitTypeParameters(
diff --git a/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
index 7780d46..2df3107 100644
--- a/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
@@ -4,7 +4,6 @@
 
 import 'dart:async';
 
-import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -13,7 +12,6 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_dart.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
-import 'package:meta/meta.dart';
 
 /**
  * The optional generator for prefix that should be used for new imports.
@@ -383,32 +381,14 @@
   String importLibrary(Uri uri);
 
   /**
-   * Ensure that the [requestedLibrary] is imported into the [targetLibrary],
-   * and the top-level [requestedName] is accessible at the [targetOffset] of
-   * the file with the [targetPath].
+   * Ensure that the library with the given [uri] is imported.
    *
-   * Parameters [targetPath] and [targetOffset] are used to determine if the
-   * unprefixed reference to the [requestedName] will be shadowed by a local
-   * declaration in the target syntactic scope.
+   * If there is already an import for the requested library, return the import
+   * prefix of the existing import directive.
    *
-   * If there is already an import for the [requestedLibrary], and the
-   * [requestedName] refers to the same element in the namespace of the import
-   * directive, and the name of the element is not ambiguous in existing import
-   * directives, and the name does not conflict with existing declarations and
-   * references, return the import prefix of the existing import directive.
-   *
-   * If there is no existing import, or there is a conflict, a new import is
-   * added, possibly with an import prefix.
-   *
-   * This method can be used only alone, and only once.
+   * If there is no existing import, a new import is added.
    */
-  ImportLibraryElementResult importLibraryElement({
-    @required ResolvedLibraryResult targetLibrary,
-    @required String targetPath,
-    @required int targetOffset,
-    @required LibraryElement requestedLibrary,
-    @required Element requestedElement,
-  });
+  ImportLibraryElementResult importLibraryElement(Uri uri);
 
   /**
    * Optionally create an edit to replace the given [typeAnnotation] with the
diff --git a/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart b/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
index dd4a046..eb6ee1c 100644
--- a/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
+++ b/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
@@ -211,6 +211,9 @@
   }
 
   @override
+  void declaredExtension(ExtensionDeclaration declaration) {}
+
+  @override
   void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
     if (varDecl.name.name == targetName) {
       // Type provided by the element in computeFull above
diff --git a/pkg/analyzer_plugin/lib/utilities/range_factory.dart b/pkg/analyzer_plugin/lib/utilities/range_factory.dart
index f41003d..1f58ec2 100644
--- a/pkg/analyzer_plugin/lib/utilities/range_factory.dart
+++ b/pkg/analyzer_plugin/lib/utilities/range_factory.dart
@@ -70,6 +70,24 @@
   }
 
   /**
+   * Return a source range that covers the given [item] (including a leading or
+   * trailing comma as appropriate) in the containing [list].
+   */
+  SourceRange nodeInList<T extends AstNode>(NodeList<T> list, T item) {
+    if (list.length == 1) {
+      return node(item);
+    }
+    final index = list.indexOf(item);
+    // Remove trailing comma.
+    if (index == 0) {
+      return startStart(item, list[1]);
+    } else {
+      // Remove leading comma.
+      return endEnd(list[index - 1], item);
+    }
+  }
+
+  /**
    * Return a source range that covers all of the given [nodes] (that is, from
    * the start of the first node to the end of the last node.
    */
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
index a0bfa57..5b4985f 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
@@ -7,6 +7,7 @@
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.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/analysis/driver.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
@@ -685,10 +686,16 @@
     DartChangeBuilderImpl builder = newBuilder();
     await builder.addFileEdit(path, (FileEditBuilder builder) {
       builder.addInsertion(11, (EditBuilder builder) {
-        (builder as DartEditBuilder).writeLocalVariableDeclaration('foo',
-            initializerWriter: () {
-          builder.write('null');
-        }, type: A.declaredElement.type);
+        (builder as DartEditBuilder).writeLocalVariableDeclaration(
+          'foo',
+          initializerWriter: () {
+            builder.write('null');
+          },
+          type: A.declaredElement.instantiate(
+            typeArguments: [],
+            nullabilitySuffix: NullabilitySuffix.star,
+          ),
+        );
       });
     });
     SourceEdit edit = getEdit(builder);
@@ -710,8 +717,14 @@
     DartChangeBuilderImpl builder = newBuilder();
     await builder.addFileEdit(path, (FileEditBuilder builder) {
       builder.addInsertion(11, (EditBuilder builder) {
-        (builder as DartEditBuilder).writeLocalVariableDeclaration('foo',
-            type: A.declaredElement.type, typeGroupName: 'type');
+        (builder as DartEditBuilder).writeLocalVariableDeclaration(
+          'foo',
+          type: A.declaredElement.instantiate(
+            typeArguments: [],
+            nullabilitySuffix: NullabilitySuffix.star,
+          ),
+          typeGroupName: 'type',
+        );
       });
     });
     SourceEdit edit = getEdit(builder);
@@ -740,8 +753,15 @@
     DartChangeBuilderImpl builder = newBuilder();
     await builder.addFileEdit(path, (FileEditBuilder builder) {
       builder.addInsertion(11, (EditBuilder builder) {
-        (builder as DartEditBuilder).writeLocalVariableDeclaration('foo',
-            isFinal: true, type: A.declaredElement.type, typeGroupName: 'type');
+        (builder as DartEditBuilder).writeLocalVariableDeclaration(
+          'foo',
+          isFinal: true,
+          type: A.declaredElement.instantiate(
+            typeArguments: [],
+            nullabilitySuffix: NullabilitySuffix.star,
+          ),
+          typeGroupName: 'type',
+        );
       });
     });
     SourceEdit edit = getEdit(builder);
@@ -1245,12 +1265,12 @@
     String content = 'class A {} class B<E> {}';
     addSource(path, content);
     InterfaceType typeA = await _getType(path, 'A');
-    InterfaceType typeB = await _getType(path, 'B');
+    InterfaceType typeBofA = await _getType(path, 'B', typeArguments: [typeA]);
 
     DartChangeBuilderImpl builder = newBuilder();
     await builder.addFileEdit(path, (FileEditBuilder builder) {
       builder.addInsertion(content.length - 1, (EditBuilder builder) {
-        (builder as DartEditBuilder).writeType(typeB.instantiate([typeA]));
+        (builder as DartEditBuilder).writeType(typeBofA);
       });
     });
     SourceEdit edit = getEdit(builder);
@@ -1317,8 +1337,10 @@
     String content = 'class A<T> {}';
     addSource(path, content);
 
-    InterfaceType typeA = await _getType(path, 'A');
-    DartType typeT = typeA.typeParameters.single.type;
+    var classA = await _getClassElement(path, 'A');
+    DartType typeT = classA.typeParameters.single.instantiate(
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
 
     var builder = newBuilder();
     await builder.addFileEdit(path, (builder) {
@@ -1382,13 +1404,22 @@
     var builder = newBuilder();
     await builder.addFileEdit(path, (builder) {
       builder.addInsertion(content.length - 1, (builder) {
-        builder.writeType(a1.type);
+        builder.writeType(a1.instantiate(
+          typeArguments: [],
+          nullabilitySuffix: NullabilitySuffix.star,
+        ));
         builder.write(' a1; ');
 
-        builder.writeType(a2.type);
+        builder.writeType(a2.instantiate(
+          typeArguments: [],
+          nullabilitySuffix: NullabilitySuffix.star,
+        ));
         builder.write(' a2; ');
 
-        builder.writeType(b.type);
+        builder.writeType(b.instantiate(
+          typeArguments: [],
+          nullabilitySuffix: NullabilitySuffix.star,
+        ));
         builder.write(' b;');
       });
     }, importPrefixGenerator: prefixGenerator);
@@ -1571,9 +1602,16 @@
     return result.element.accessors.firstWhere((v) => v.name == name);
   }
 
-  Future<InterfaceType> _getType(String path, String name) async {
+  Future<InterfaceType> _getType(
+    String path,
+    String name, {
+    List<DartType> typeArguments = const [],
+  }) async {
     ClassElement classElement = await _getClassElement(path, name);
-    return classElement.type;
+    return classElement.instantiate(
+      typeArguments: typeArguments,
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
   }
 }
 
@@ -1760,7 +1798,12 @@
     CompilationUnit unit = (await driver.getResult(path))?.unit;
     ClassDeclaration classC = unit.declarations[2] as ClassDeclaration;
     DartLinkedEditBuilderImpl builder = new DartLinkedEditBuilderImpl(null);
-    builder.addSuperTypesAsSuggestions(classC.declaredElement.type);
+    builder.addSuperTypesAsSuggestions(
+      classC.declaredElement.instantiate(
+        typeArguments: [],
+        nullabilitySuffix: NullabilitySuffix.star,
+      ),
+    );
     List<LinkedEditSuggestion> suggestions = builder.suggestions;
     expect(suggestions, hasLength(4));
     expect(suggestions.map((s) => s.value),
@@ -2785,9 +2828,16 @@
       }
     }
 
+    var targetType = targetElement.instantiate(
+      typeArguments: targetElement.typeParameters
+          .map((e) => e.instantiate(nullabilitySuffix: NullabilitySuffix.star))
+          .toList(),
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+
     TypeSystem typeSystem = await session.typeSystem;
     var inherited = new InheritanceManager3(typeSystem).getInherited(
-      targetElement.type,
+      targetType,
       new Name(null, nameToOverride),
     );
 
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
index 51b5c38..fbf1131 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
@@ -16,9 +16,7 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(ImportLibraryElementTest);
     defineReflectiveTests(ImportLibraryElement_existingImport_Test);
-    defineReflectiveTests(ImportLibraryElement_incompleteCode_Test);
     defineReflectiveTests(ImportLibraryElement_newImport_withoutPrefix_Test);
-    defineReflectiveTests(ImportLibraryElement_newImport_withPrefix_Test);
   });
 }
 
@@ -160,124 +158,6 @@
 }
 
 @reflectiveTest
-class ImportLibraryElement_incompleteCode_Test extends _Base {
-  test_fieldDeclaration_atEnd() async {
-    newFile('/home/test/lib/a.dart', content: 'class A {}');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-class C {
-  A^
-}
-''',
-      uriStr: 'package:test/a.dart',
-      name: 'A',
-      expectedCode: r'''
-import 'package:test/a.dart';
-
-class C {
-  A
-}
-''',
-    );
-  }
-
-  test_fieldDeclaration_beforeReturnType() async {
-    newFile('/home/test/lib/a.dart', content: 'class A {}');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-class C {
-  A^
-  
-  A foo() => null;
-}
-''',
-      uriStr: 'package:test/a.dart',
-      name: 'A',
-      expectedCode: r'''
-import 'package:test/a.dart';
-
-class C {
-  A
-  
-  A foo() => null;
-}
-''',
-    );
-  }
-
-  test_formalParameter_end() async {
-    newFile('/home/test/lib/a.dart', content: 'class AAA {}');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-f(AAA^) {}
-''',
-      uriStr: 'package:test/a.dart',
-      name: 'AAA',
-      expectedCode: r'''
-import 'package:test/a.dart';
-
-f(AAA) {}
-''',
-    );
-  }
-
-  test_formalParameter_start() async {
-    newFile('/home/test/lib/a.dart', content: 'class AAA {}');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-f(^AAA) {}
-''',
-      uriStr: 'package:test/a.dart',
-      name: 'AAA',
-      expectedCode: r'''
-import 'package:test/a.dart';
-
-f(AAA) {}
-''',
-    );
-  }
-
-  test_topLevelVariable_atEnd() async {
-    newFile('/home/test/lib/a.dart', content: 'class A {}');
-    newFile('/home/test/lib/b.dart', content: r'''
-export 'a.dart';
-''');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-A^
-''',
-      uriStr: 'package:test/a.dart',
-      name: 'A',
-      expectedCode: r'''
-import 'package:test/a.dart';
-
-A
-''',
-    );
-  }
-
-  test_topLevelVariable_beforeReturnType() async {
-    newFile('/home/test/lib/a.dart', content: 'class A {}');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-A^
-
-A foo() => null;
-''',
-      uriStr: 'package:test/a.dart',
-      name: 'A',
-      expectedCode: r'''
-import 'package:test/a.dart';
-
-A
-
-A foo() => null;
-''',
-    );
-  }
-}
-
-@reflectiveTest
 class ImportLibraryElement_newImport_withoutPrefix_Test extends _Base {
   test_constructorName_name() async {
     newFile('/home/test/lib/a.dart', content: r'''
@@ -540,369 +420,6 @@
 }
 
 @reflectiveTest
-class ImportLibraryElement_newImport_withPrefix_Test extends _Base {
-  test_existingImport_nameIsAmbiguous() async {
-    newFile('/home/test/lib/a.dart', content: 'class C {}');
-    newFile('/home/test/lib/b.dart', content: 'class C {}');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-import 'package:test/a.dart';
-import 'package:test/b.dart';
-''',
-      uriStr: 'package:test/b.dart',
-      name: 'C',
-      expectedPrefix: 'prefix0',
-      expectedCode: r'''
-import 'package:test/a.dart';
-import 'package:test/b.dart';
-import 'package:test/b.dart' as prefix0;
-''',
-    );
-  }
-
-  test_existingImport_nameIsAmbiguous_prefixed() async {
-    newFile('/home/test/lib/a.dart', content: 'class C {}');
-    newFile('/home/test/lib/b.dart', content: 'class C {}');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-import 'package:test/a.dart' as p;
-import 'package:test/b.dart' as p;
-''',
-      uriStr: 'package:test/b.dart',
-      name: 'C',
-      expectedCode: r'''
-import 'package:test/a.dart' as p;
-import 'package:test/b.dart' as p;
-import 'package:test/b.dart';
-''',
-    );
-  }
-
-  test_nameIsAmbiguous() async {
-    newFile('/home/test/lib/a.dart', content: 'class C {}');
-    newFile('/home/test/lib/b.dart', content: 'class C {}');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-import 'package:test/a.dart';
-''',
-      uriStr: 'package:test/b.dart',
-      name: 'C',
-      expectedPrefix: 'prefix0',
-      expectedCode: r'''
-import 'package:test/a.dart';
-import 'package:test/b.dart' as prefix0;
-''',
-    );
-  }
-
-  test_shadow_otherName_imported() async {
-    newFile('/home/test/lib/a.dart', content: r'''
-class A {}
-''');
-    newFile('/home/test/lib/b.dart', content: r'''
-class A {}
-class B {}
-''');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-import 'package:test/a.dart';
-
-A a;
-''',
-      uriStr: 'package:test/b.dart',
-      name: 'B',
-      expectedPrefix: 'prefix0',
-      expectedCode: r'''
-import 'package:test/a.dart';
-import 'package:test/b.dart' as prefix0;
-
-A a;
-''',
-    );
-  }
-
-  test_shadow_otherName_inherited() async {
-    newFile('/home/test/lib/b.dart', content: '''
-int foo = 0;
-int bar = 0;
-''');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-class A {
-  void bar() {}
-}
-
-class X extends A {
-  voif f() {
-    bar();
-  }
-}
-''',
-      uriStr: 'package:test/b.dart',
-      name: 'foo',
-      expectedPrefix: 'prefix0',
-      expectedCode: r'''
-import 'package:test/b.dart' as prefix0;
-
-class A {
-  void bar() {}
-}
-
-class X extends A {
-  voif f() {
-    bar();
-  }
-}
-''',
-    );
-  }
-
-  test_shadowed_class() async {
-    newFile('/home/test/lib/a.dart', content: 'class C {}');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-import 'package:test/a.dart';
-
-class C {}
-''',
-      uriStr: 'package:test/a.dart',
-      name: 'C',
-      expectedPrefix: 'prefix0',
-      expectedCode: r'''
-import 'package:test/a.dart';
-import 'package:test/a.dart' as prefix0;
-
-class C {}
-''',
-    );
-  }
-
-  test_shadowed_class_inPart() async {
-    newFile('/home/test/lib/a.dart', content: 'class C {}');
-    newFile('/home/test/lib/p.dart', content: 'class C {}');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-part 'p.dart';
-''',
-      uriStr: 'package:test/a.dart',
-      name: 'C',
-      expectedPrefix: 'prefix0',
-      expectedCode: r'''
-import 'package:test/a.dart' as prefix0;
-
-part 'p.dart';
-''',
-    );
-  }
-
-  test_shadowed_formalParameter() async {
-    newFile('/home/test/lib/a.dart', content: r'''
-var foo = 0;
-''');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-void f(int foo) {^}
-''',
-      uriStr: 'package:test/a.dart',
-      name: 'foo',
-      expectedPrefix: 'prefix0',
-      expectedCode: r'''
-import 'package:test/a.dart' as prefix0;
-
-void f(int foo) {}
-''',
-    );
-  }
-
-  test_shadowed_function() async {
-    newFile('/home/test/lib/a.dart', content: r'''
-var foo = 0;
-''');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-void foo() {^}
-''',
-      uriStr: 'package:test/a.dart',
-      name: 'foo',
-      expectedPrefix: 'prefix0',
-      expectedCode: r'''
-import 'package:test/a.dart' as prefix0;
-
-void foo() {}
-''',
-    );
-  }
-
-  test_shadowed_function_local_after() async {
-    newFile('/home/test/lib/a.dart', content: r'''
-var foo = 0;
-''');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-void f() {
-  void foo() {}
-^}
-''',
-      uriStr: 'package:test/a.dart',
-      name: 'foo',
-      expectedPrefix: 'prefix0',
-      expectedCode: r'''
-import 'package:test/a.dart' as prefix0;
-
-void f() {
-  void foo() {}
-}
-''',
-    );
-  }
-
-  test_shadowed_function_local_before() async {
-    newFile('/home/test/lib/a.dart', content: r'''
-var foo = 0;
-''');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-void f() {^
-  void foo() {}
-}
-''',
-      uriStr: 'package:test/a.dart',
-      name: 'foo',
-      expectedPrefix: 'prefix0',
-      expectedCode: r'''
-import 'package:test/a.dart' as prefix0;
-
-void f() {
-  void foo() {}
-}
-''',
-    );
-  }
-
-  test_shadowed_importPrefix() async {
-    newFile('/home/test/lib/a.dart', content: 'int foo = 0;');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-import 'dart:math' as foo;
-''',
-      uriStr: 'package:test/a.dart',
-      name: 'foo',
-      expectedPrefix: 'prefix0',
-      expectedCode: r'''
-import 'dart:math' as foo;
-
-import 'package:test/a.dart' as prefix0;
-''',
-    );
-  }
-
-  test_shadowed_localVariable_after() async {
-    newFile('/home/test/lib/a.dart', content: 'int foo = 0;');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-main() {
-  var foo = '';
-^}
-''',
-      uriStr: 'package:test/a.dart',
-      name: 'foo',
-      expectedPrefix: 'prefix0',
-      expectedCode: r'''
-import 'package:test/a.dart' as prefix0;
-
-main() {
-  var foo = '';
-}
-''',
-    );
-  }
-
-  test_shadowed_localVariable_before() async {
-    newFile('/home/test/lib/a.dart', content: 'int foo = 0;');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-main() {^
-  var foo = '';
-}
-''',
-      uriStr: 'package:test/a.dart',
-      name: 'foo',
-      expectedPrefix: 'prefix0',
-      expectedCode: r'''
-import 'package:test/a.dart' as prefix0;
-
-main() {
-  var foo = '';
-}
-''',
-    );
-  }
-
-  test_shadowed_method() async {
-    newFile('/home/test/lib/a.dart', content: 'int foo = 0;');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-class A {
-  void foo() {}
-  
-  void bar() {^}
-}
-''',
-      uriStr: 'package:test/a.dart',
-      name: 'foo',
-      expectedPrefix: 'prefix0',
-      expectedCode: r'''
-import 'package:test/a.dart' as prefix0;
-
-class A {
-  void foo() {}
-  
-  void bar() {}
-}
-''',
-    );
-  }
-
-  test_shadowed_typeParameter_class() async {
-    newFile('/home/test/lib/a.dart', content: r'''
-class A {}
-''');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-class C<A> {^}
-''',
-      uriStr: 'package:test/a.dart',
-      name: 'A',
-      expectedPrefix: 'prefix0',
-      expectedCode: r'''
-import 'package:test/a.dart' as prefix0;
-
-class C<A> {}
-''',
-    );
-  }
-
-  test_shadowed_typeParameter_function() async {
-    newFile('/home/test/lib/a.dart', content: r'''
-class A {}
-''');
-    await _assertImportLibraryElement(
-      initialCode: r'''
-void f<A>() {^}
-''',
-      uriStr: 'package:test/a.dart',
-      name: 'A',
-      expectedPrefix: 'prefix0',
-      expectedCode: r'''
-import 'package:test/a.dart' as prefix0;
-
-void f<A>() {}
-''',
-    );
-  }
-}
-
-@reflectiveTest
 class ImportLibraryElementTest extends _Base {
   test_thisLibrary() async {
     await _assertImportLibraryElement(
@@ -939,21 +456,14 @@
     var path = convertPath('/home/test/lib/test.dart');
     newFile(path, content: initialCode);
 
-    var resolvedLibrary = await session.getResolvedLibrary(path);
     var requestedLibrary = await session.getLibraryByUri(uriStr);
-
     var requestedElement = requestedLibrary.exportNamespace.get(name);
     expect(requestedElement, isNotNull, reason: '`$name` in $uriStr');
 
     var builder = newBuilder();
     await builder.addFileEdit(path, (builder) {
-      var result = builder.importLibraryElement(
-        targetLibrary: resolvedLibrary,
-        targetPath: path,
-        targetOffset: offset,
-        requestedLibrary: requestedLibrary,
-        requestedElement: requestedElement,
-      );
+      var uri = Uri.parse(uriStr);
+      var result = builder.importLibraryElement(uri);
       expect(result.prefix, expectedPrefix);
     });
 
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/syntactic_scope_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/syntactic_scope_test.dart
deleted file mode 100644
index 1a39dee..0000000
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/syntactic_scope_test.dart
+++ /dev/null
@@ -1,689 +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/analysis/experiments.dart';
-import 'package:analyzer_plugin/src/utilities/change_builder/dart/syntactic_scope.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../../../../support/abstract_context.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(NotSyntacticScopeReferencedNamesCollectorTest);
-    defineReflectiveTests(SyntacticScopeNamesCollectorTest);
-  });
-}
-
-@reflectiveTest
-class NotSyntacticScopeReferencedNamesCollectorTest
-    extends AbstractContextTest {
-  test_notSyntacticScopeNames() async {
-    var path = convertPath('/home/test/lib/test.dart');
-
-    newFile('/home/test/lib/a.dart', content: r'''
-var N1;
-''');
-
-    newFile(path, content: r'''
-import 'package:test/a.dart';
-
-class A {
-  var N2;
-  
-  void N3() {}
-  
-  get N4 => null;
-  
-  set N5(_) {}
-}
-
-var S1;
-
-class B<S2> extends A {
-  var S3;
-  
-  void S4() {}
-  
-  get S5 => null;
-  
-  set S6(_) {}
-  
-  void f<S7>(S8) {
-    var S9;
-    N1;
-    N1 = 0;
-    N2;
-    N3;
-    N4;
-    N5 = 0;
-    B;
-    S1;
-    S1 = 0;
-    S2;
-    S3;
-    S4;
-    S5;
-    S6 = 0;
-    S7;
-    S8;
-    S9;
-  }
-}
-''');
-
-    var resolvedUnit = await session.getResolvedUnit(path);
-    var collector = NotSyntacticScopeReferencedNamesCollector(
-      resolvedUnit.libraryElement,
-      (<String>[]
-            ..addAll(List.generate(20, (i) => 'N$i'))
-            ..addAll(List.generate(20, (i) => 'S$i')))
-          .toSet(),
-    );
-    resolvedUnit.unit.accept(collector);
-
-    expect(
-      collector.importedNames,
-      containsPair('N1', Uri.parse('package:test/a.dart')),
-    );
-
-    expect(
-      collector.inheritedNames,
-      unorderedEquals(['N2', 'N3', 'N4', 'N5']),
-    );
-  }
-
-  test_notSyntacticScopeNames_constructorName_name() async {
-    var path = convertPath('/home/test/lib/test.dart');
-
-    newFile('/home/test/lib/a.dart', content: r'''
-class N1 {
-  N1.N2();
-}
-''');
-
-    newFile(path, content: r'''
-import 'package:test/a.dart';
-
-void f() {
-  N1.N2();
-}
-''');
-
-    var resolvedUnit = await session.getResolvedUnit(path);
-    var collector = NotSyntacticScopeReferencedNamesCollector(
-      resolvedUnit.libraryElement,
-      ['N1', 'N2'].toSet(),
-    );
-    resolvedUnit.unit.accept(collector);
-
-    expect(
-      collector.importedNames,
-      containsPair('N1', Uri.parse('package:test/a.dart')),
-    );
-
-    expect(collector.inheritedNames, isEmpty);
-  }
-
-  test_referencedNames() async {
-    var path = convertPath('/home/test/lib/test.dart');
-    newFile(path, content: r'''
-class N1 {}
-
-N2 N3<N4>(N5 N6, N7) {
-  N7.N8(N9);
-}
-''');
-
-    var resolvedUnit = await session.getResolvedUnit(path);
-    var collector = NotSyntacticScopeReferencedNamesCollector(
-      resolvedUnit.libraryElement,
-      <String>[].toSet(),
-    );
-    resolvedUnit.unit.accept(collector);
-
-    expect(
-      collector.referencedNames,
-      unorderedEquals(['N1', 'N2', 'N3', 'N4', 'N5', 'N6', 'N7', 'N8', 'N9']),
-    );
-  }
-}
-
-@reflectiveTest
-class SyntacticScopeNamesCollectorTest extends AbstractContextTest {
-  test_Block() {
-    _assertScopeNames(code: r'''
-N1() {
-  ^1
-  N2 N3, N4;
-  ^2
-  {
-    ^3
-    var N5;
-    ^4
-  }
-  ^5
-  var N6;
-  ^6
-  {
-    ^7
-    var N7;
-    ^8
-  }
-  ^9
-}
-''', expected: r'''
-1: N3, N4, N6
-2: N3, N4, N6
-3: N3, N4, N5, N6
-4: N3, N4, N5, N6
-5: N3, N4, N6
-6: N3, N4, N6
-7: N3, N4, N6, N7
-8: N3, N4, N6, N7
-9: N3, N4, N6
-''');
-  }
-
-  test_CatchClause() {
-    _assertScopeNames(code: r'''
-N1() {
-  ^1
-  try {
-    var N2;
-    ^2
-  } on N3 catch (N4, N5) {
-    ^3
-  } catch (N6) {
-    ^4
-  }
-  ^5
-}
-''', expected: r'''
-1: {}
-2: N2
-3: N4, N5
-4: N6
-5: {}
-''');
-  }
-
-  test_ClassDeclaration() {
-    _assertScopeNames(code: r'''
-class N1<N2 ^1> extends ^2 N3<N4 ^3> with ^4 N5, N6 implements ^5 N7, N8 {
-  ^6
-  N9 N10, N11;
-  
-  N1.N12() {}
-  
-  N13 N14<N15>() {}
-  
-  ^7
-}
-
-class N16<N17> {
-  ^8
-}
-''', expected: r'''
-1: N2
-2: N2
-3: N2
-4: N2
-5: N2
-6: N2, N10, N11, N14
-7: N2, N10, N11, N14
-8: N17
-''');
-  }
-
-  test_ClassTypeAlias() {
-    _assertScopeNames(code: r'''
-class N1<N2 ^1> = N3<N4 ^2> with N5<N6 ^3> implements N7;
-''', expected: r'''
-1: N2
-2: N2
-3: N2
-''');
-  }
-
-  test_CollectionForElement_ForEachPartsWithDeclaration() {
-    _enableExperiments();
-    _assertScopeNames(code: r'''
-N1() {
-  [
-    0 ^1,
-    for (var N2 in N3 ^2) {
-      ^3
-    },
-    ^4
-    for (var N4 in N5) {
-      ^5
-    },
-    ^6
-  ];
-  ^7
-}
-''', expected: r'''
-1: {}
-2: {}
-3: N2
-4: {}
-5: N4
-6: {}
-7: {}
-''');
-  }
-
-  test_CollectionForElement_ForPartsWithDeclarations() {
-    _enableExperiments();
-    _assertScopeNames(code: r'''
-N1() {
-  [
-    0 ^1,
-    for (var N2 = 0 ^2; ^3; ^4) {
-      ^5
-    },
-    ^6
-    for (var N3 = 0 ^7; ^8; ^9) {
-      ^10
-    },
-    ^11
-  ];
-  ^12
-}
-''', expected: r'''
-1: {}
-2: N2
-3: N2
-4: N2
-5: N2
-6: {}
-7: N3
-8: N3
-9: N3
-10: N3
-11: {}
-12: {}
-''');
-  }
-
-  test_ConstructorDeclaration() {
-    _assertScopeNames(code: r'''
-class N1<N2> extends N3 {
-  N1.N4(N5, this.N6, ^1) {
-    ^2
-  }
-  ^3
-}
-''', expected: r'''
-1: N2, N5, N6
-2: N2, N5, N6
-3: N2
-''');
-  }
-
-  test_ForEachStatement_identifier() {
-    _assertScopeNames(code: r'''
-N1() {
-  ^1
-  for (N2 in N3 ^2) {
-    ^3
-  }
-  ^4
-}
-''', expected: r'''
-1: {}
-2: {}
-3: {}
-4: {}
-''');
-  }
-
-  test_ForEachStatement_iterable() {
-    _assertScopeNames(code: r'''
-N1() {
-  for (var N2 in (){ var N3; ^1 }()) {
-    ^2
-  }
-  ^3
-}
-''', expected: r'''
-1: N3
-2: N2
-3: {}
-''');
-  }
-
-  test_ForEachStatement_loopVariable() {
-    _assertScopeNames(code: r'''
-N1() {
-  ^1
-  for (var N2 in N3 ^2) {
-    ^3
-  }
-  ^4
-}
-''', expected: r'''
-1: {}
-2: {}
-3: N2
-4: {}
-''');
-  }
-
-  test_FormalParameter_functionTyped() {
-    _assertScopeNames(code: r'''
-N1 N2(N3 N4(N5 N6 ^1, N7), N8 ^2) {
-  ^3
-}
-''', expected: r'''
-1: N4, N6, N7, N8
-2: N4, N8
-3: N4, N8
-''');
-  }
-
-  test_FormalParameter_nameOnly() {
-    _assertScopeNames(code: r'''
-N1 N2(^1N3^2) {
-  ^3
-}
-''', expected: r'''
-1: {}
-2: {}
-3: N3
-''');
-  }
-
-  test_ForStatement2_ForEachPartsWithDeclaration() {
-    _enableExperiments();
-    _assertScopeNames(code: r'''
-N1() {
-  ^1
-  for (var N2 in N3 ^2) {
-    ^3
-  }
-  ^4
-}
-''', expected: r'''
-1: {}
-2: {}
-3: N2
-4: {}
-''');
-  }
-
-  test_ForStatement2_ForEachPartsWithIdentifier() {
-    _enableExperiments();
-    _assertScopeNames(code: r'''
-N1() {
-  ^1
-  for (N2 in N3 ^2) {
-    ^3
-  }
-  ^4
-}
-''', expected: r'''
-1: {}
-2: {}
-3: {}
-4: {}
-''');
-  }
-
-  test_ForStatement2_ForPartsWithDeclarations_condition() {
-    _enableExperiments();
-    _assertScopeNames(code: r'''
-N1() {
-  ^1
-  for (N1 N2; (){ var N3; ^2 }(); ^3) {
-    ^4
-  }
-  ^5
-}
-''', expected: r'''
-1: {}
-2: N2, N3
-3: N2
-4: N2
-5: {}
-''');
-  }
-
-  test_ForStatement2_ForPartsWithDeclarations_updaters() {
-    _enableExperiments();
-    _assertScopeNames(code: r'''
-N1() {
-  ^1
-  for (N1 N2; ^2; (){ var N3; ^3 }()) {
-    ^4
-  }
-  ^5
-}
-''', expected: r'''
-1: {}
-2: N2
-3: N2, N3
-4: N2
-5: {}
-''');
-  }
-
-  test_ForStatement2_ForPartsWithDeclarations_variables() {
-    _enableExperiments();
-    _assertScopeNames(code: r'''
-N1() {
-  ^1
-  for (N2 N3, N4 ^2; N5 ^3; N6 ^4) {
-    ^5
-  }
-  ^6
-}
-''', expected: r'''
-1: {}
-2: N3, N4
-3: N3, N4
-4: N3, N4
-5: N3, N4
-6: {}
-''');
-  }
-
-  test_ForStatement_condition() {
-    _assertScopeNames(code: r'''
-N1() {
-  ^1
-  for (N1 N2; (){ var N3; ^2 }(); ^3) {
-    ^4
-  }
-  ^5
-}
-''', expected: r'''
-1: {}
-2: N2, N3
-3: N2
-4: N2
-5: {}
-''');
-  }
-
-  test_ForStatement_updaters() {
-    _assertScopeNames(code: r'''
-N1() {
-  ^1
-  for (N1 N2; ^2; (){ var N3; ^3 }()) {
-    ^4
-  }
-  ^5
-}
-''', expected: r'''
-1: {}
-2: N2
-3: N2, N3
-4: N2
-5: {}
-''');
-  }
-
-  test_ForStatement_variables() {
-    _assertScopeNames(code: r'''
-N1() {
-  ^1
-  for (N2 N3, N4 ^2; N5 ^3; N6 ^4) {
-    ^5
-  }
-  ^6
-}
-''', expected: r'''
-1: {}
-2: N3, N4
-3: N3, N4
-4: N3, N4
-5: N3, N4
-6: {}
-''');
-  }
-
-  test_FunctionDeclaration() {
-    _assertScopeNames(code: r'''
-N1 N2<N3 extends N4 ^1>(N5 N6 ^2, [N7 N8 = N9, N10]) {
-  ^3
-}
-''', expected: r'''
-1: N3
-2: N3, N6, N8, N10
-3: N3, N6, N8, N10
-''');
-  }
-
-  test_FunctionTypeAlias() {
-    _assertScopeNames(code: r'''
-typedef N1 N2<N3 ^1>(N3 N4, N5 ^2);
-''', expected: r'''
-1: N3
-2: N3, N4, N5
-''');
-  }
-
-  test_GenericFunctionType() {
-    _assertScopeNames(code: r'''
-N1 Function<N2 ^1>(N3, N4 N5 ^2) N6;
-''', expected: r'''
-1: N2
-2: N2, N5
-''');
-  }
-
-  test_GenericTypeAlias() {
-    _assertScopeNames(code: r'''
-typedef N1<N2 ^1> = Function<N3 ^2>(N4 N5, N6 ^3);
-''', expected: r'''
-1: N2
-2: N2, N3
-3: N2, N3, N5
-''');
-  }
-
-  test_MethodDeclaration() {
-    _assertScopeNames(code: r'''
-class N1<N2> {
-  N3 N4, N5;
-  
-  ^1
-  
-  N6 ^2 N7<N8 ^3>(N9 N10, N11 ^4) {
-    ^5
-  }
-}
-''', expected: r'''
-1: N2, N4, N5, N7
-2: N2, N4, N5, N7, N8
-3: N2, N4, N5, N7, N8
-4: N2, N4, N5, N7, N8, N10, N11
-5: N2, N4, N5, N7, N8, N10, N11
-''');
-  }
-
-  test_MixinDeclaration() {
-    _assertScopeNames(code: r'''
-mixin N1<N2> on N3, N4 ^1 implements N5 ^2 {
-  ^3
-  N6 N7, N8;
-  ^4
-  
-  N9(N10 ^5) {
-    ^6
-  }
-  
-  ^7
-}
-''', expected: r'''
-1: N2
-2: N2
-3: N2, N7, N8, N9
-4: N2, N7, N8, N9
-5: N2, N7, N8, N9, N10
-6: N2, N7, N8, N9, N10
-7: N2, N7, N8, N9
-''');
-  }
-
-  void _assertScopeNames({String code, String expected}) {
-    var matches = RegExp(r'\^\d{1,2}').allMatches(code).toList();
-
-    var matchOffsets = <String, int>{};
-    var delta = 0;
-    for (var match in matches) {
-      var newStart = match.start - delta;
-      var newEnd = match.end - delta;
-      matchOffsets[code.substring(newStart + 1, newEnd)] = newStart;
-      delta += match.end - match.start;
-      code = code.substring(0, newStart) + code.substring(newEnd);
-    }
-
-    var path = convertPath('/home/test/lib/a.dart');
-    newFile(path, content: code);
-
-    var parsedResult = session.getParsedUnit(path);
-    expect(parsedResult.errors, isEmpty);
-
-    var unit = parsedResult.unit;
-    var buffer = StringBuffer();
-    for (var offsetName in matchOffsets.keys) {
-      var offset = matchOffsets[offsetName];
-      var nameSet = Set<String>();
-
-      unit.accept(SyntacticScopeNamesCollector(nameSet, offset));
-
-      var nameList = nameSet.toList();
-      nameList.sort((a, b) {
-        expect(a.startsWith('N'), isTrue);
-        expect(b.startsWith('N'), isTrue);
-        return int.parse(a.substring(1)) - int.parse(b.substring(1));
-      });
-
-      buffer.write('$offsetName: ');
-      if (nameList.isEmpty) {
-        buffer.writeln('{}');
-      } else {
-        buffer.writeln(nameList.join(', '));
-      }
-    }
-
-    var actual = buffer.toString();
-    if (actual != expected) {
-      print(actual);
-    }
-    expect(actual, expected);
-  }
-
-  void _enableExperiments() {
-    createAnalysisOptionsFile(
-      experiments: [
-        EnableString.control_flow_collections,
-        EnableString.spread_collections,
-      ],
-    );
-  }
-}
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/test_all.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/test_all.dart
index 9d53f53..06a0484 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/test_all.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/test_all.dart
@@ -5,12 +5,10 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'import_library_element_test.dart' as import_library_element;
-import 'syntactic_scope_test.dart' as syntactic_scope;
 
 /// Utility for manually running all tests.
 main() {
   defineReflectiveSuite(() {
     import_library_element.main();
-    syntactic_scope.main();
   });
 }
diff --git a/pkg/analyzer_plugin/test/src/utilities/visitors/local_declaration_visitor_test.dart b/pkg/analyzer_plugin/test/src/utilities/visitors/local_declaration_visitor_test.dart
index 673e646..f19508e 100644
--- a/pkg/analyzer_plugin/test/src/utilities/visitors/local_declaration_visitor_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/visitors/local_declaration_visitor_test.dart
@@ -64,6 +64,9 @@
   void declaredClassTypeAlias(ClassTypeAlias declaration) {}
 
   @override
+  void declaredExtension(ExtensionDeclaration declaration) {}
+
+  @override
   void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {}
 
   @override
diff --git a/pkg/compiler/lib/src/constants/constant_system.dart b/pkg/compiler/lib/src/constants/constant_system.dart
index 2d154b7..47aa5ed 100644
--- a/pkg/compiler/lib/src/constants/constant_system.dart
+++ b/pkg/compiler/lib/src/constants/constant_system.dart
@@ -636,7 +636,7 @@
   BigInt foldNums(num left, num right) {
     num ratio = left / right;
     if (ratio.isNaN || ratio.isInfinite) return null;
-    return new BigInt.from(ratio.truncate().toInt());
+    return new BigInt.from(ratio.truncateToDouble());
   }
 
   @override
diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index ba35b89..0ec782d 100644
--- a/pkg/compiler/lib/src/ir/static_type.dart
+++ b/pkg/compiler/lib/src/ir/static_type.dart
@@ -180,7 +180,7 @@
     // subtypes of Object (not just interface types), and function types are
     // considered subtypes of Function.
     if (superclass.typeParameters.isEmpty) {
-      return superclass.rawType;
+      return typeEnvironment.coreTypes.legacyRawType(superclass);
     }
     while (type is ir.TypeParameterType) {
       type = (type as ir.TypeParameterType).parameter.bound;
@@ -196,7 +196,7 @@
       return superclass.bottomType;
     }
     // TODO(johnniwinther): Should we assert that this doesn't happen?
-    return superclass.rawType;
+    return typeEnvironment.coreTypes.legacyRawType(superclass);
   }
 
   /// Computes the result type of the property access [node] on a receiver of
@@ -781,7 +781,8 @@
   ir.DartType visitConstructorInvocation(ir.ConstructorInvocation node) {
     ArgumentTypes argumentTypes = _visitArguments(node.arguments);
     ir.DartType resultType = node.arguments.types.isEmpty
-        ? new ExactInterfaceType.from(node.target.enclosingClass.rawType)
+        ? new ExactInterfaceType.from(
+            typeEnvironment.coreTypes.legacyRawType(node.target.enclosingClass))
         : new ExactInterfaceType(
             node.target.enclosingClass, node.arguments.types);
     _expressionTypeCache[node] = resultType;
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 8b4374b..c797e3b 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -2603,6 +2603,8 @@
         return runtimeTypeName(_commonElements.objectClass);
       case JsGetName.FUNCTION_CLASS_TYPE_NAME:
         return runtimeTypeName(_commonElements.functionClass);
+      case JsGetName.JS_FUNCTION_CLASS_TYPE_NAME:
+        return runtimeTypeName(_commonElements.jsJavaScriptFunctionClass);
       case JsGetName.FUTURE_CLASS_TYPE_NAME:
         return runtimeTypeName(_commonElements.futureClass);
       case JsGetName.BOOL_RECIPE:
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 9a56acf..0dfdaf9 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types_new.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_new.dart
@@ -299,14 +299,12 @@
     // TODO(sra): We might be in a context where the class type variable has an
     // index, even though in the general case it is not at a specific index.
 
-    if (_closedWorld.isUsedAsMixin(cls)) return null;
-
-    // TODO(fishythefish): We should only check strict subclasses for
-    // non-trivial substitutions in the general case. We should check all strict
-    // subtypes only when [cls] is a mixin (above) or when [cls] is a type
-    // argument to `extractTypeArguments`.
     ClassHierarchy classHierarchy = _closedWorld.classHierarchy;
-    if (classHierarchy.anyStrictSubtypeOf(cls, (ClassEntity subclass) {
+    var test = mustCheckAllSubtypes(_closedWorld, cls)
+        ? classHierarchy.anyStrictSubtypeOf
+        : classHierarchy.anyStrictSubclassOf;
+
+    if (test(cls, (ClassEntity subclass) {
       return !_rtiSubstitutions.isTrivialSubstitution(subclass, cls);
     })) {
       return null;
@@ -470,6 +468,10 @@
   }
 }
 
+bool mustCheckAllSubtypes(JClosedWorld world, ClassEntity cls) =>
+    world.isUsedAsMixin(cls) ||
+    world.extractTypeArgumentsInterfacesNewRti.contains(cls);
+
 class _RulesetEntry {
   final InterfaceType _targetType;
   List<InterfaceType> _supertypes;
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 704c07a..871cdd2 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
@@ -30,6 +30,7 @@
     show RuntimeTypesChecks, RuntimeTypesEncoder;
 import '../../js_backend/runtime_types_new.dart'
     show RecipeEncoder, RecipeEncoding;
+import '../../js_backend/runtime_types_new.dart' as newRti;
 import '../../js_backend/runtime_types_resolution.dart' show RuntimeTypesNeed;
 import '../../js_model/elements.dart' show JGeneratorBody, JSignatureMethod;
 import '../../js_model/type_recipe.dart'
@@ -852,8 +853,12 @@
   void associateNamedTypeVariablesNewRti() {
     for (TypeVariableType typeVariable in _codegenWorld.namedTypeVariablesNewRti
         .union(_lateNamedTypeVariablesNewRti)) {
-      for (ClassEntity entity
-          in _classHierarchy.subtypesOf(typeVariable.element.typeDeclaration)) {
+      ClassEntity declaration = typeVariable.element.typeDeclaration;
+      Iterable<ClassEntity> subtypes =
+          newRti.mustCheckAllSubtypes(_closedWorld, declaration)
+              ? _classHierarchy.subtypesOf(declaration)
+              : _classHierarchy.subclassesOf(declaration);
+      for (ClassEntity entity in subtypes) {
         Class cls = _classes[entity];
         if (cls == null) continue;
         cls.namedTypeVariablesNewRti.add(typeVariable);
diff --git a/pkg/compiler/lib/src/js_model/js_world.dart b/pkg/compiler/lib/src/js_model/js_world.dart
index c24c3a9..ca2f1be 100644
--- a/pkg/compiler/lib/src/js_model/js_world.dart
+++ b/pkg/compiler/lib/src/js_model/js_world.dart
@@ -76,6 +76,9 @@
   final Set<MemberEntity> processedMembers;
 
   @override
+  final Set<ClassEntity> extractTypeArgumentsInterfacesNewRti;
+
+  @override
   final ClassHierarchy classHierarchy;
 
   final JsKernelToElementMap elementMap;
@@ -109,6 +112,7 @@
       this.liveInstanceMembers,
       this.assignedInstanceMembers,
       this.processedMembers,
+      this.extractTypeArgumentsInterfacesNewRti,
       this.mixinUses,
       this.typesImplementedBySubclasses,
       this.classHierarchy,
@@ -154,6 +158,8 @@
 
     Set<ClassEntity> implementedClasses = source.readClasses().toSet();
     Set<ClassEntity> liveNativeClasses = source.readClasses().toSet();
+    Set<ClassEntity> extractTypeArgumentsInterfacesNewRti =
+        source.readClasses().toSet();
     Set<MemberEntity> liveInstanceMembers = source.readMembers().toSet();
     Set<MemberEntity> assignedInstanceMembers = source.readMembers().toSet();
     Set<MemberEntity> processedMembers = source.readMembers().toSet();
@@ -191,6 +197,7 @@
         liveInstanceMembers,
         assignedInstanceMembers,
         processedMembers,
+        extractTypeArgumentsInterfacesNewRti,
         mixinUses,
         typesImplementedBySubclasses,
         classHierarchy,
@@ -217,6 +224,7 @@
     noSuchMethodData.writeToDataSink(sink);
     sink.writeClasses(implementedClasses);
     sink.writeClasses(liveNativeClasses);
+    sink.writeClasses(extractTypeArgumentsInterfacesNewRti);
     sink.writeMembers(liveInstanceMembers);
     sink.writeMembers(assignedInstanceMembers);
     sink.writeMembers(processedMembers);
@@ -558,6 +566,11 @@
   MemberAccess getMemberAccess(MemberEntity member) {
     return memberAccess[member];
   }
+
+  @override
+  void registerExtractTypeArguments(ClassEntity interface) {
+    extractTypeArgumentsInterfacesNewRti.add(interface);
+  }
 }
 
 class KernelSorter implements Sorter {
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 1bf43b4..1c8687b 100644
--- a/pkg/compiler/lib/src/js_model/js_world_builder.dart
+++ b/pkg/compiler/lib/src/js_model/js_world_builder.dart
@@ -130,6 +130,8 @@
     Set<MemberEntity> processedMembers =
         map.toBackendMemberSet(closedWorld.liveMemberUsage.keys);
 
+    Set<ClassEntity> extractTypeArgumentsInterfacesNewRti = {};
+
     RuntimeTypesNeed rtiNeed;
 
     List<FunctionEntity> callMethods = <FunctionEntity>[];
@@ -223,6 +225,7 @@
         liveInstanceMembers /*..addAll(callMethods)*/,
         assignedInstanceMembers,
         processedMembers,
+        extractTypeArgumentsInterfacesNewRti,
         mixinUses,
         typesImplementedBySubclasses,
         new ClassHierarchyImpl(
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index 5dcee7e..cd8c5b9 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -51,10 +51,7 @@
   Dart2jsTarget(this.name, this.flags);
 
   @override
-  bool get legacyMode => flags.legacyMode;
-
-  @override
-  bool get enableNoSuchMethodForwarders => !flags.legacyMode;
+  bool get enableNoSuchMethodForwarders => true;
 
   @override
   List<String> get extraRequiredLibraries => _requiredLibraries[name];
@@ -120,7 +117,7 @@
                 new ir.StringLiteral(arg.name)..fileOffset = arg.fileOffset,
                 arg.value)
               ..fileOffset = arg.fileOffset;
-          })), keyType: coreTypes.stringClass.rawType)
+          })), keyType: coreTypes.stringLegacyRawType)
             ..isConst = (arguments.named.length == 0)
             ..fileOffset = arguments.fileOffset,
           new ir.IntLiteral(kind)..fileOffset = offset,
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index ab3bc02..2e65567 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -4040,6 +4040,7 @@
     List<DartType> typeArguments = <DartType>[];
 
     if (options.experimentNewRti) {
+      closedWorld.registerExtractTypeArguments(cls);
       HInstruction instanceType =
           HInstanceEnvironment(object, _abstractValueDomain.dynamicType);
       add(instanceType);
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 77b1dac..1197751 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -3478,8 +3478,6 @@
     js.Expression recipe = encoding.recipe;
 
     for (TypeVariableType typeVariable in encoding.typeVariables) {
-      // TODO(fishythefish): Constraint the type variable to only be emitted on
-      // (subtypes of) the environment type.
       _registry.registerTypeUse(TypeUse.namedTypeVariableNewRti(typeVariable));
     }
 
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index e7f5930..89c2271 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -70,6 +70,10 @@
 
   Iterable<MemberEntity> get processedMembers;
 
+  /// Returns the set of interfaces passed as type arguments to the internal
+  /// `extractTypeArguments` function.
+  Set<ClassEntity> get extractTypeArgumentsInterfacesNewRti;
+
   ClassHierarchy get classHierarchy;
 
   AnnotationsData get annotationsData;
@@ -202,6 +206,9 @@
   /// Returns the set of read, write, and invocation accesses found on [member]
   /// during the closed world computation.
   MemberAccess getMemberAccess(MemberEntity member);
+
+  /// Registers [interface] as a type argument to `extractTypeArguments`.
+  void registerExtractTypeArguments(ClassEntity interface);
 }
 
 abstract class OpenWorld implements World {
diff --git a/pkg/compiler/tool/generate_kernel.dart b/pkg/compiler/tool/generate_kernel.dart
index 817ba97..1201ae8 100644
--- a/pkg/compiler/tool/generate_kernel.dart
+++ b/pkg/compiler/tool/generate_kernel.dart
@@ -25,7 +25,7 @@
 main(List<String> args) async {
   ArgResults flags = _argParser.parse(args);
   var options = new CompilerOptions()
-    ..target = new Dart2jsTarget("dart2js", new TargetFlags(legacyMode: true))
+    ..target = new Dart2jsTarget("dart2js", new TargetFlags())
     ..packagesFileUri = Uri.base.resolve('.packages')
     ..setExitCodeOnProblem = true
     ..linkedDependencies = [
diff --git a/pkg/dart_internal/pubspec.yaml b/pkg/dart_internal/pubspec.yaml
index 2ffe0ee..a411212 100644
--- a/pkg/dart_internal/pubspec.yaml
+++ b/pkg/dart_internal/pubspec.yaml
@@ -1,5 +1,5 @@
 name: dart_internal
-version: 0.1.6
+version: 0.1.7
 author: "Dart Team <misc@dartlang.org>"
 homepage: http://www.dartlang.org
 description: >
@@ -16,4 +16,4 @@
 environment:
   # Restrict the upper bound so that we can remove support for this in a later
   # version of the SDK without it being a breaking change.
-  sdk: ">=2.0.0-dev.12.0 <2.6.0"
+  sdk: ">=2.0.0-dev.12.0 <2.7.0"
diff --git a/pkg/dartfix/lib/src/driver.dart b/pkg/dartfix/lib/src/driver.dart
index fa4c91a..ee93476 100644
--- a/pkg/dartfix/lib/src/driver.dart
+++ b/pkg/dartfix/lib/src/driver.dart
@@ -16,6 +16,7 @@
 import 'package:dartfix/src/context.dart';
 import 'package:dartfix/src/options.dart';
 import 'package:dartfix/src/util.dart';
+import 'package:path/path.dart' as path;
 import 'package:pub_semver/pub_semver.dart';
 
 class Driver {
@@ -127,6 +128,14 @@
     if (options.pedanticFixes) {
       params.includePedanticFixes = true;
     }
+    String dir = options.outputDir;
+    if (dir != null) {
+      if (!path.isAbsolute(dir)) {
+        dir = path.absolute(dir);
+      }
+      dir = path.canonicalize(dir);
+      params.outputDir = dir;
+    }
     Map<String, dynamic> json =
         await server.send(EDIT_REQUEST_DARTFIX, params.toJson());
 
diff --git a/pkg/dartfix/lib/src/options.dart b/pkg/dartfix/lib/src/options.dart
index 545196a..02bcf3a 100644
--- a/pkg/dartfix/lib/src/options.dart
+++ b/pkg/dartfix/lib/src/options.dart
@@ -9,19 +9,20 @@
 import 'package:dartfix/src/context.dart';
 import 'package:path/path.dart' as path;
 
+const excludeFixOption = 'excludeFix';
 const forceOption = 'force';
 const includeFixOption = 'fix';
-const excludeFixOption = 'excludeFix';
+const outputDirOption = 'outputDir';
 const overwriteOption = 'overwrite';
 const pedanticOption = 'pedantic';
 const requiredOption = 'required';
 
 const _binaryName = 'dartfix';
 const _colorOption = 'color';
-const _serverSnapshot = 'server';
+const _helpOption = 'help';
 
 // options only supported by server 1.22.2 and greater
-const _helpOption = 'help';
+const _serverSnapshot = 'server';
 const _verboseOption = 'verbose';
 
 /// Command line options for `dartfix`.
@@ -40,6 +41,7 @@
 
   final bool force;
   final bool showHelp;
+  final String outputDir;
   final bool overwrite;
   final bool useColor;
   final bool verbose;
@@ -48,6 +50,7 @@
       : force = results[forceOption] as bool,
         includeFixes = (results[includeFixOption] as List ?? []).cast<String>(),
         excludeFixes = (results[excludeFixOption] as List ?? []).cast<String>(),
+        outputDir = results[outputDirOption] as String,
         overwrite = results[overwriteOption] as bool,
         pedanticFixes = results[pedanticOption] as bool,
         requiredFixes = results[requiredOption] as bool,
@@ -104,7 +107,12 @@
           negatable: false)
       ..addFlag(_colorOption,
           help: 'Use ansi colors when printing messages.',
-          defaultsTo: Ansi.terminalSupportsAnsi);
+          defaultsTo: Ansi.terminalSupportsAnsi)
+      //
+      // Hidden options.
+      //
+      ..addOption(outputDirOption,
+          help: 'Path to the output directory', hide: true);
 
     context ??= Context();
 
diff --git a/pkg/dartfix/test/src/options_test.dart b/pkg/dartfix/test/src/options_test.dart
index c6c87ed..beb90d0 100644
--- a/pkg/dartfix/test/src/options_test.dart
+++ b/pkg/dartfix/test/src/options_test.dart
@@ -30,6 +30,7 @@
     String normalOut,
     bool pedanticFixes = false,
     bool requiredFixes = false,
+    String outputDir,
     bool overwrite = false,
     String serverSnapshot,
     List<String> targetSuffixes,
@@ -55,6 +56,7 @@
     expect(options.force, force);
     expect(options.pedanticFixes, pedanticFixes);
     expect(options.requiredFixes, requiredFixes);
+    expect(options.outputDir, outputDir);
     expect(options.overwrite, overwrite);
     expect(options.serverSnapshot, serverSnapshot);
     expect(options.showHelp, showHelp);
@@ -115,6 +117,10 @@
         errorOut: 'Expected directory, but found', exitCode: 21);
   });
 
+  test('outputDir', () {
+    parse(['--outputDir=bar', 'foo'], outputDir: 'bar');
+  });
+
   test('overwrite', () {
     parse(['--overwrite', 'foo'], overwrite: true, targetSuffixes: ['foo']);
   });
@@ -145,12 +151,6 @@
   });
 }
 
-void expectOneFileTarget(Options options, String fileName) {
-  expect(options.targets, hasLength(1));
-  final target = options.targets[0];
-  expect(target.endsWith(fileName), isTrue);
-}
-
 void expectContains(Iterable<String> collection, String suffix) {
   for (String elem in collection) {
     if (elem.endsWith(suffix)) {
@@ -159,3 +159,9 @@
   }
   fail('Expected one of $collection\n  to end with "$suffix"');
 }
+
+void expectOneFileTarget(Options options, String fileName) {
+  expect(options.targets, hasLength(1));
+  final target = options.targets[0];
+  expect(target.endsWith(fileName), isTrue);
+}
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index 6ae1c24..e521784 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -1003,10 +1003,10 @@
       }
     }
     if (classElem.library.isDartAsync) {
-      if (classElem == types.futureOrType.element) {
+      if (classElem == types.futureOrElement) {
         var typeParamT = classElem.typeParameters[0].type;
         var typeT = _emitType(typeParamT);
-        var futureOfT = _emitType(types.futureType.instantiate([typeParamT]));
+        var futureOfT = _emitType(types.futureType2(typeParamT));
         body.add(js.statement('''
             #.is = function is_FutureOr(o) {
               return #.is(o) || #.is(o);
@@ -1207,7 +1207,7 @@
       List<js_ast.Method> methods,
       List<js_ast.Statement> body,
       List<js_ast.Statement> deferredSupertypes) {
-    if (classElem.type.isObject) {
+    if (classElem.isDartCoreObject) {
       body.add(_emitClassStatement(classElem, className, null, methods));
       return;
     }
@@ -1423,7 +1423,7 @@
     bool hasJsPeer = _extensionTypes.isNativeClass(classElem);
     bool hasIterator = false;
 
-    if (type.isObject) {
+    if (classElem.isDartCoreObject) {
       // Dart does not use ES6 constructors.
       // Add an error to catch any invalid usage.
       jsMethods.add(
@@ -1788,7 +1788,7 @@
   }
 
   bool _implementsIterable(InterfaceType t) =>
-      t.interfaces.any((i) => i.element.type == types.iterableType);
+      t.interfaces.any((i) => i.element == types.iterableElement);
 
   /// Support for adapting dart:core Iterable to ES6 versions.
   ///
@@ -2005,7 +2005,7 @@
   /// Ensure `dartx.` symbols we will use are present.
   void _initExtensionSymbols(ClassElement classElem) {
     if (_extensionTypes.hasNativeSubtype(classElem.type) ||
-        classElem.type.isObject) {
+        classElem.isDartCoreObject) {
       for (var members in [classElem.methods, classElem.accessors]) {
         for (var m in members) {
           if (!m.isAbstract && !m.isStatic && m.isPublic) {
@@ -2055,7 +2055,7 @@
       if (elements.isEmpty) return;
 
       if (!name.startsWith('Static')) {
-        var proto = classElem.type.isObject
+        var proto = classElem.isDartCoreObject
             ? js.call('Object.create(null)')
             : runtimeCall('get${name}s(#.__proto__)', [className]);
         elements.insert(0, js_ast.Property(propertyName('__proto__'), proto));
@@ -2347,7 +2347,7 @@
     // Get the supertype's unnamed constructor.
     superCtor ??= element.supertype?.element?.unnamedConstructor;
     if (superCtor == null) {
-      assert(element.type.isObject ||
+      assert(element.isDartCoreObject ||
           element.isMixin ||
           options.unsafeForceCompile);
       return null;
@@ -2381,7 +2381,7 @@
   }
 
   bool _hasUnnamedConstructor(ClassElement e) {
-    if (e.type.isObject) return false;
+    if (e.isDartCoreObject) return false;
     var ctor = e.unnamedConstructor;
     if (ctor != null && !ctor.isSynthetic) return true;
     return e.fields.any((f) => !f.isStatic && !f.isSynthetic);
@@ -2966,7 +2966,7 @@
     //
     // In the body of an `async`, `await` is generated simply as `yield`.
     var gen = emitGeneratorFn([]);
-    var dartAsync = types.futureType.element.library;
+    var dartAsync = types.futureElement.library;
     return js.call('#.async(#, #)',
         [emitLibraryName(dartAsync), _emitType(returnType), gen]);
   }
@@ -4458,15 +4458,15 @@
       return _emitType(value.toTypeValue());
     }
     if (type is InterfaceType) {
-      if (type.element == types.listType.element) {
+      if (type.element == types.listElement) {
         return _emitConstList(type.typeArguments[0],
             value.toListValue().map(_emitDartObject).toList());
       }
-      if (type.element == types.setType.element) {
+      if (type.element == types.setElement) {
         return _emitConstSet(type.typeArguments[0],
             value.toSetValue().map(_emitDartObject).toList());
       }
-      if (type.element == types.mapType.element) {
+      if (type.element == types.mapElement) {
         var entries = <js_ast.Expression>[];
         value.toMapValue().forEach((key, value) {
           entries.add(_emitDartObject(key));
@@ -5866,7 +5866,7 @@
       body.accept(finder);
       if (finder.hasYield) {
         var genFn = js_ast.Fun([], body, isGenerator: true);
-        var asyncLibrary = emitLibraryName(types.futureType.element.library);
+        var asyncLibrary = emitLibraryName(types.futureElement.library);
         return js_ast.Yield(js.call(
             '#.async(#, #)', [asyncLibrary, _emitType(yieldType), genFn]));
       }
@@ -6278,19 +6278,19 @@
     }
     var type = functionType.returnType;
 
-    InterfaceType expectedType;
+    ClassElement expectedElement;
     if (element.isAsynchronous) {
       if (element.isGenerator) {
         // Stream<T> -> T
-        expectedType = types.streamType;
+        expectedElement = types.streamElement;
       } else {
         // Future<T> -> T
-        expectedType = types.futureType;
+        expectedElement = types.futureElement;
       }
     } else {
       if (element.isGenerator) {
         // Iterable<T> -> T
-        expectedType = types.iterableType;
+        expectedElement = types.iterableElement;
       } else {
         // T -> T
         return type;
@@ -6298,9 +6298,9 @@
     }
     if (type.isDynamic) return type;
     if (type is InterfaceType &&
-        (type.element == expectedType.element ||
-            expectedType == types.futureType &&
-                type.element == types.futureOrType.element)) {
+        (type.element == expectedElement ||
+            expectedElement == types.futureElement &&
+                type.element == types.futureOrElement)) {
       return type.typeArguments[0];
     }
     // TODO(leafp): The above only handles the case where the return type
@@ -6311,8 +6311,12 @@
   js_ast.Expression _throwUnsafe(String message) => runtimeCall(
       'throw(Error(#))', [js.escapedString("compile error: $message")]);
 
-  Null _unreachable(Object node) {
-    throw UnsupportedError('tried to generate an unreachable node: `$node`');
+  js_ast.Expression _unreachable(Object node) {
+    var message = 'tried to generate an unreachable node: `$node`';
+    if (options.unsafeForceCompile) {
+      return _throwUnsafe(message);
+    }
+    throw UnsupportedError(message);
   }
 
   /// Unused, see methods for emitting declarations.
@@ -6584,7 +6588,7 @@
         return _emitAwaitFor(forParts, jsBody);
       }
     }
-    return _unreachable(forParts);
+    return _unreachable(forParts).toStatement();
   }
 
   @override
diff --git a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
index 98c7b54..a306bfb 100644
--- a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
@@ -227,7 +227,7 @@
   var method = classElement.lookUpMethod(
       FunctionElement.NO_SUCH_METHOD_METHOD_NAME, classElement.library);
   var definingClass = method?.enclosingElement;
-  return definingClass is ClassElement && !definingClass.type.isObject;
+  return definingClass is ClassElement && !definingClass.isDartCoreObject;
 }
 
 /// Returns true if this class is of the form:
diff --git a/pkg/dev_compiler/lib/src/analyzer/extension_types.dart b/pkg/dev_compiler/lib/src/analyzer/extension_types.dart
index d0e80e6..833a968 100644
--- a/pkg/dev_compiler/lib/src/analyzer/extension_types.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/extension_types.dart
@@ -168,7 +168,7 @@
   /// For example for dart:_interceptors `JSArray` this will return "Array",
   /// referring to the JavaScript built-in `Array` type.
   List<String> getNativePeers(ClassElement classElem) {
-    if (classElem.type.isObject) return ['Object'];
+    if (classElem.isDartCoreObject) return ['Object'];
     var names = getAnnotationName(
         classElem,
         (a) =>
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
index 2024848..01d77e4 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
@@ -252,6 +252,7 @@
     /// runtime call.
     js_ast.TemporaryId initPrivateNameSymbol() {
       var idName = name.endsWith('=') ? name.replaceAll('=', '_') : name;
+      idName = idName.replaceAll('.', '_');
       var id = js_ast.TemporaryId(idName);
       moduleItems.add(js.statement('const # = #.privateName(#, #)',
           [id, runtimeModule, emitLibraryName(library), js.string(name)]));
@@ -262,6 +263,16 @@
     return privateNames.putIfAbsent(name, initPrivateNameSymbol);
   }
 
+  /// Emits a private name JS Symbol for [name] unique to a Dart class [cls].
+  ///
+  /// This is now required for fields of constant objects that may be
+  /// overridden within the same library.
+  @protected
+  js_ast.TemporaryId emitClassPrivateNameSymbol(
+      Library library, String className, String memberName) {
+    return emitPrivateNameSymbol(library, '$className.$memberName');
+  }
+
   /// Emits an expression to set the property [nameExpr] on the class [className],
   /// with [value].
   ///
diff --git a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
index d90fa57..4f1d80b 100644
--- a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
+++ b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
@@ -121,9 +121,6 @@
     return result;
   }
 
-  /// Dispose the Analysis Context used for summary conversion.
-  void dispose() => _resynth.context.dispose();
-
   void verifyReferences() {
     _references.forEach((element, reference) {
       // Ensure each reference has a corresponding node.
@@ -799,11 +796,11 @@
       return TypeLiteral(_visitDartType(obj.toTypeValue()));
     }
     if (type is a.InterfaceType) {
-      if (type.element == types.listType.element) {
+      if (type.element == types.listElement) {
         return ListLiteral(obj.toListValue().map(_visitConstant).toList(),
             typeArgument: _visitDartType(type.typeArguments[0]), isConst: true);
       }
-      if (type.element == types.mapType.element) {
+      if (type.element == types.mapElement) {
         var entries = obj
             .toMapValue()
             .entries
@@ -898,7 +895,6 @@
       as a.AnalysisContextImpl;
   context.sourceFactory = a.SourceFactory(
       [a.DartUriResolver(sdk), a.InSummaryUriResolver(null, summaryData)]);
-  context.useSdkCachePartition = false;
   // TODO(jmesserly): do we need to set analysisOptions or declaredVariables?
   return context;
 }
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index bf38ecb..c741457 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -312,7 +312,6 @@
     var converter = AnalyzerToKernel(sdkSummaryPath, summaryPaths);
     opts.sdkSummaryComponent = converter.convertSdk();
     opts.inputSummariesComponents = converter.convertSummaries();
-    converter.dispose();
   }
 
   fe.DdcResult result;
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index fd5a3de..396b0ae 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -263,11 +263,12 @@
   FunctionNode get currentFunction => _currentFunction;
 
   @override
-  InterfaceType get privateSymbolType => _privateSymbolClass.rawType;
+  InterfaceType get privateSymbolType =>
+      _coreTypes.legacyRawType(_privateSymbolClass);
 
   @override
   InterfaceType get internalSymbolType =>
-      _coreTypes.internalSymbolClass.rawType;
+      _coreTypes.legacyRawType(_coreTypes.internalSymbolClass);
 
   js_ast.Program emitModule(Component component, List<Component> summaries,
       List<Uri> summaryUris, Map<Uri, String> moduleImportForSummary) {
@@ -794,7 +795,7 @@
         getBaseClass(isMixinAliasClass(c) ? 0 : mixins.length),
         emitDeferredType(supertype),
       ]));
-      supertype = supertype.classNode.rawType;
+      supertype = _coreTypes.legacyRawType(supertype.classNode);
     }
     var baseClass = emitClassRef(supertype);
 
@@ -1351,7 +1352,7 @@
       for (var ctor in allConstructors) {
         var memberName = _constructorName(ctor.name.name);
         var type = _emitAnnotatedFunctionType(
-            ctor.function.functionType.withoutTypeParameters, ctor);
+            ctor.function.thisFunctionType.withoutTypeParameters, ctor);
         constructors.add(js_ast.Property(memberName, type));
       }
       emitSignature('Constructor', constructors);
@@ -1392,7 +1393,7 @@
     FunctionType result;
     if (!f.positionalParameters.any(isCovariantParameter) &&
         !f.namedParameters.any(isCovariantParameter)) {
-      result = f.functionType;
+      result = f.thisFunctionType;
     } else {
       reifyParameter(VariableDeclaration p) =>
           isCovariantParameter(p) ? _coreTypes.objectClass.thisType : p.type;
@@ -1405,7 +1406,7 @@
           f.positionalParameters.map(reifyParameter).toList(), f.returnType,
           namedParameters: f.namedParameters.map(reifyNamedParameter).toList()
             ..sort(),
-          typeParameters: f.functionType.typeParameters,
+          typeParameters: f.thisFunctionType.typeParameters,
           requiredParameterCount: f.requiredParameterCount);
     }
     return _getTypeFromClass(result, member.enclosingClass, fromClass)
@@ -1846,7 +1847,7 @@
     assert(!member.isAccessor);
 
     var superMethodType =
-        substituteType(superMember.function.functionType) as FunctionType;
+        substituteType(superMember.function.thisFunctionType) as FunctionType;
     var function = member.function;
 
     var body = <js_ast.Statement>[];
@@ -2058,7 +2059,7 @@
   void _registerExtensionType(
       Class c, String jsPeerName, List<js_ast.Statement> body) {
     var className = _emitTopLevelName(c);
-    if (_typeRep.isPrimitive(c.rawType)) {
+    if (_typeRep.isPrimitive(_coreTypes.legacyRawType(c))) {
       body.add(runtimeStatement(
           'definePrimitiveHashCode(#.prototype)', [className]));
     }
@@ -2285,7 +2286,7 @@
     if (c == null) {
       return _isObjectMember(name);
     }
-    c = _typeRep.getImplementationClass(c.rawType) ?? c;
+    c = _typeRep.getImplementationClass(_coreTypes.legacyRawType(c)) ?? c;
     if (_extensionTypes.isNativeClass(c)) {
       var member = _lookupForwardedMember(c, name);
 
@@ -2461,9 +2462,9 @@
     // TODO(jmesserly): do we even need this for mirrors, since statics are not
     // commonly reflected on?
     if (_options.emitMetadata && _reifyFunctionType(p.function)) {
-      body.add(
-          _emitFunctionTagged(nameExpr, p.function.functionType, topLevel: true)
-              .toStatement());
+      body.add(_emitFunctionTagged(nameExpr, p.function.thisFunctionType,
+              topLevel: true)
+          .toStatement());
     }
 
     _currentUri = savedUri;
@@ -2795,10 +2796,9 @@
 
   void _emitVirtualFieldSymbols(Class c, List<js_ast.Statement> body) {
     _classProperties.virtualFields.forEach((field, virtualField) {
-      body.add(js.statement('const # = Symbol(#);', [
-        virtualField,
-        js.string('${getLocalClassName(c)}.${field.name.name}')
-      ]));
+      var symbol = emitClassPrivateNameSymbol(
+          c.enclosingLibrary, getLocalClassName(c), field.name.name);
+      body.add(js.statement('const # = #;', [virtualField, symbol]));
     });
   }
 
@@ -2916,14 +2916,14 @@
     var gen = emitGeneratorFn((_) => []);
     // Return type of an async body is `Future<flatten(T)>`, where T is the
     // declared return type.
-    var returnType = _types.unfutureType(function.functionType.returnType);
+    var returnType = _types.unfutureType(function.thisFunctionType.returnType);
     return js.call('#.async(#, #)',
         [emitLibraryName(_coreTypes.asyncLibrary), _emitType(returnType), gen]);
   }
 
   /// Gets the expected return type of a `sync*` or `async*` body.
   DartType _getExpectedReturnType(FunctionNode f, Class expected) {
-    var type = f.functionType.returnType;
+    var type = f.thisFunctionType.returnType;
     if (type is InterfaceType) {
       var match = _hierarchy.getTypeAsInstanceOf(type, expected);
       if (match != null) return match.typeArguments[0];
@@ -3276,7 +3276,7 @@
     var conditionType = condition.getStaticType(_types);
     var jsCondition = _visitExpression(condition);
 
-    var boolType = _coreTypes.boolClass.rawType;
+    var boolType = _coreTypes.boolLegacyRawType;
     if (conditionType is FunctionType &&
         conditionType.requiredParameterCount == 0 &&
         conditionType.returnType == boolType) {
@@ -3516,7 +3516,7 @@
     //
     // TODO(jmesserly): we may want a helper if these become common. For now the
     // full desugaring seems okay.
-    var streamIterator = _asyncStreamIteratorClass.rawType;
+    var streamIterator = _coreTypes.legacyRawType(_asyncStreamIteratorClass);
     var createStreamIter = js_ast.Call(
         _emitConstructorName(
             streamIterator,
@@ -3819,7 +3819,8 @@
     if (_reifyFunctionType(func)) {
       declareFn = js_ast.Block([
         declareFn,
-        _emitFunctionTagged(_emitVariableRef(node.variable), func.functionType)
+        _emitFunctionTagged(
+                _emitVariableRef(node.variable), func.thisFunctionType)
             .toStatement()
       ]);
     }
@@ -4006,7 +4007,7 @@
       // TODO(jmesserly): we could tag static/top-level function types once
       // in the module initialization, rather than at the point where they
       // escape.
-      return _emitFunctionTagged(result, target.function.functionType);
+      return _emitFunctionTagged(result, target.function.thisFunctionType);
     }
     return result;
   }
@@ -4136,13 +4137,13 @@
   }
 
   bool _isDynamicOrFunction(DartType t) =>
-      t == _coreTypes.functionClass.rawType || t == const DynamicType();
+      t == _coreTypes.functionLegacyRawType || t == const DynamicType();
 
   js_ast.Expression _emitUnaryOperator(
       Expression expr, Member target, InvocationExpression node) {
     var op = node.name.name;
     if (target != null) {
-      var dispatchType = target.enclosingClass.rawType;
+      var dispatchType = _coreTypes.legacyRawType(target.enclosingClass);
       if (_typeRep.unaryOperationIsPrimitive(dispatchType)) {
         if (op == '~') {
           if (_typeRep.isNumber(dispatchType)) {
@@ -4312,7 +4313,7 @@
     // https://github.com/dart-lang/sdk/issues/33293
     if (target != null) {
       var targetClass = target.enclosingClass;
-      var leftType = targetClass.rawType;
+      var leftType = _coreTypes.legacyRawType(targetClass);
       var rightType = right.getStaticType(_types);
 
       if (_typeRep.binaryOperationIsPrimitive(leftType, rightType) ||
@@ -4411,7 +4412,9 @@
       Expression left, Member target, Expression right,
       {bool negated = false}) {
     var targetClass = target?.enclosingClass;
-    var leftType = targetClass?.rawType ?? left.getStaticType(_types);
+    var leftType = targetClass != null
+        ? _coreTypes.legacyRawType(targetClass)
+        : left.getStaticType(_types);
 
     // Conceptually `x == y` in Dart is defined as:
     //
@@ -4710,8 +4713,7 @@
   }
 
   bool _isNull(Expression expr) =>
-      expr is NullLiteral ||
-      expr.getStaticType(_types) == _coreTypes.nullClass.rawType;
+      expr is NullLiteral || expr.getStaticType(_types) == _coreTypes.nullType;
 
   bool _doubleEqIsIdentity(Expression left, Expression right) {
     // If we statically know LHS or RHS is null we can use ==.
@@ -4789,7 +4791,7 @@
     }
 
     var type = ctorClass.typeParameters.isEmpty
-        ? ctorClass.rawType
+        ? _coreTypes.legacyRawType(ctorClass)
         : InterfaceType(ctorClass, args.types);
 
     if (isFromEnvironmentInvocation(_coreTypes, node)) {
@@ -4841,7 +4843,8 @@
   js_ast.Expression _emitJSInteropNew(Member ctor, Arguments args) {
     var ctorClass = ctor.enclosingClass;
     if (isJSAnonymousType(ctorClass)) return _emitObjectLiteral(args);
-    return js_ast.New(_emitConstructorName(ctorClass.rawType, ctor),
+    return js_ast.New(
+        _emitConstructorName(_coreTypes.legacyRawType(ctorClass), ctor),
         _emitArgumentList(args, types: false));
   }
 
@@ -5000,8 +5003,8 @@
     // All Dart number types map to a JS double.
     if (_typeRep.isNumber(from) && _typeRep.isNumber(to)) {
       // Make sure to check when converting to int.
-      if (from != _coreTypes.intClass.rawType &&
-          to == _coreTypes.intClass.rawType) {
+      if (from != _coreTypes.intLegacyRawType &&
+          to == _coreTypes.intLegacyRawType) {
         // TODO(jmesserly): fuse this with notNull check.
         // TODO(jmesserly): this does not correctly distinguish user casts from
         // required-for-soundness casts.
@@ -5404,8 +5407,15 @@
     entryToProperty(MapEntry<Reference, Constant> entry) {
       var constant = visitConstant(entry.value);
       var member = entry.key.asField;
-      return js_ast.Property(
-          _emitMemberName(member.name.name, member: member), constant);
+      var cls = member.enclosingClass;
+      // Enums cannot be overridden, so we can safely use the field name
+      // directly.  Otherwise, use a private symbol in case the field
+      // was overridden.
+      var symbol = cls.isEnum
+          ? _emitMemberName(member.name.name, member: member)
+          : emitClassPrivateNameSymbol(
+              cls.enclosingLibrary, getLocalClassName(cls), member.name.name);
+      return js_ast.Property(symbol, constant);
     }
 
     var type = visitInterfaceType(node.getType(_types) as InterfaceType);
diff --git a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
index 07810f3..c49ba46 100644
--- a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
+++ b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
@@ -119,7 +119,7 @@
     if (target == null) return true; // dynamic call
     if (target.name.name == 'toString' &&
         receiver != null &&
-        receiver.getStaticType(types) == coreTypes.stringClass.rawType) {
+        receiver.getStaticType(types) == coreTypes.stringLegacyRawType) {
       // TODO(jmesserly): `class String` in dart:core does not explicitly
       // declare `toString`, which results in a target of `Object.toString` even
       // when the reciever type is known to be `String`. So we work around it.
@@ -143,7 +143,8 @@
       // implementation class in dart:_interceptors, for example `JSString`.
       //
       // This allows us to find the `@notNull` annotation if it exists.
-      var implClass = jsTypeRep.getImplementationClass(targetClass.rawType);
+      var implClass = jsTypeRep
+          .getImplementationClass(coreTypes.legacyRawType(targetClass));
       if (implClass != null) {
         var member =
             jsTypeRep.hierarchy.getDispatchTarget(implClass, target.name);
diff --git a/pkg/dev_compiler/lib/src/kernel/property_model.dart b/pkg/dev_compiler/lib/src/kernel/property_model.dart
index 5eca899..f1ced92 100644
--- a/pkg/dev_compiler/lib/src/kernel/property_model.dart
+++ b/pkg/dev_compiler/lib/src/kernel/property_model.dart
@@ -161,6 +161,13 @@
       if (_extensiblePrivateClasses.contains(class_)) return true;
     }
 
+    if (class_.constructors.any((c) => c.isConst)) {
+      // Always virtualize fields of a (might be) non-enum (see above) const
+      // class.  The way these are lowered by the CFE, they need to be
+      // writable from different modules even if overridden.
+      return true;
+    }
+
     // Otherwise, the field is effectively private and we only need to make it
     // virtual if it's overridden.
     return _overriddenPrivateFields.contains(field);
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index 1eb6b62..5ae85a5 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -21,9 +21,6 @@
   WidgetCreatorTracker _widgetTracker;
 
   @override
-  bool get legacyMode => false;
-
-  @override
   bool get enableSuperMixins => true;
 
   @override
@@ -163,7 +160,7 @@
           arguments.named
               .map((n) => MapEntry(SymbolLiteral(n.name), n.value))
               .toList(),
-          keyType: coreTypes.symbolClass.rawType));
+          keyType: coreTypes.symbolLegacyRawType));
     }
     return createInvocation('method', ctorArgs);
   }
diff --git a/pkg/dev_compiler/test/modular_ddc_suite.dart b/pkg/dev_compiler/test/modular_ddc_suite.dart
new file mode 100644
index 0000000..3d75a07
--- /dev/null
+++ b/pkg/dev_compiler/test/modular_ddc_suite.dart
@@ -0,0 +1,313 @@
+// 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';
+
+// TODO(vsm): Hack until we have either:
+// (1) an NNBD version of the below
+// (2) the ability to compile the primary version with NNBD
+List<String> _nnbdOptOut = ['sdk'];
+String _test_package = 'ddc_modular_test';
+
+Uri sdkRoot = Platform.script.resolve("../../../");
+Options _options;
+String _dartdevcScript;
+String _buildSdkScript;
+String _patchSdkScript;
+String _sdkDevRuntime;
+
+main(List<String> args) async {
+  _options = Options.parse(args);
+  await _resolveScripts();
+  await runSuite(
+      sdkRoot.resolve('tests/modular/'),
+      'tests/modular',
+      _options,
+      IOPipeline([
+        DDCStep(),
+        RunD8(),
+      ], cacheSharedModules: true, saveIntermediateResultsForTesting: false));
+}
+
+const sumId = DataId("sum");
+const jsId = DataId("js");
+const txtId = DataId("txt");
+
+class DDCStep implements IOModularStep {
+  @override
+  List<DataId> get resultData => const [sumId, jsId];
+
+  @override
+  bool get needsSources => true;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [sumId];
+
+  @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: ddc on $module");
+
+    Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
+    await _createPackagesFile(module, root, transitiveDependencies);
+
+    ProcessResult result;
+
+    bool nnbd = flags.contains('non-nullable');
+    bool allowErrors = nnbd && _nnbdOptOut.contains(module.name);
+
+    if (module.isSdk) {
+      assert(transitiveDependencies.isEmpty);
+
+      // Apply patches.
+      result = await _runProcess(
+          Platform.resolvedExecutable,
+          [
+            _patchSdkScript,
+            sdkRoot.toFilePath(),
+            _sdkDevRuntime,
+            'patched_sdk',
+            if (nnbd) 'sdk_nnbd'
+          ],
+          root.toFilePath());
+      _checkExitCode(result, this, module);
+
+      // Build the SDK.
+      result = await _runProcess(
+          Platform.resolvedExecutable,
+          [
+            _buildSdkScript,
+            '--dart-sdk',
+            'patched_sdk',
+            '--dart-sdk-summary=build',
+            '--summary-out',
+            '${toUri(module, sumId)}',
+            '--modules=es6',
+            if (allowErrors) '--unsafe-force-compile',
+            for (String flag in flags) '--enable-experiment=$flag',
+            '-o',
+            '${toUri(module, jsId)}',
+          ],
+          root.toFilePath());
+      _checkExitCode(result, this, module);
+    } else {
+      Module sdkModule = module.dependencies.firstWhere((m) => m.isSdk);
+      List<String> sources = module.sources
+          .map((relativeUri) => _sourceToImportUri(module, relativeUri))
+          .toList();
+      Map<String, String> _urlMappings = {};
+      if (!module.isPackage) {
+        for (var source in module.sources) {
+          var importUri = _sourceToImportUri(module, source);
+          _urlMappings[importUri] = '$source';
+        }
+      }
+      for (var dependency in transitiveDependencies) {
+        if (!dependency.isPackage && !dependency.isSdk) {
+          for (var source in dependency.sources) {
+            var importUri = _sourceToImportUri(dependency, source);
+            _urlMappings[importUri] = '$source';
+          }
+        }
+      }
+      var extraArgs = [
+        '--dart-sdk-summary',
+        '${toUri(sdkModule, sumId)}',
+        '--packages',
+        '.packages',
+      ];
+
+      Uri output = toUri(module, jsId);
+
+      List<String> args = [
+        '--packages=${sdkRoot.toFilePath()}/.packages',
+        _dartdevcScript,
+        '--modules=es6',
+        '--summarize',
+        '--no-source-map',
+        ...sources,
+        if (_urlMappings.isNotEmpty)
+          '--url-mapping=${_urlMappings.entries.map((entry) => '${entry.key},${entry.value}').join(',')}',
+        ...extraArgs,
+        for (String flag in flags) '--enable-experiment=$flag',
+        ...(transitiveDependencies
+            .where((m) => !m.isSdk)
+            .expand((m) => ['-s', '${toUri(m, sumId)}'])),
+        '-o',
+        '$output',
+      ];
+      result = await _runProcess(
+          Platform.resolvedExecutable, args, root.toFilePath());
+      _checkExitCode(result, this, module);
+    }
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("\ncached step: ddc 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, 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 'package:${_test_package}/$relativeUri';
+  }
+}
+
+Future<void> _resolveScripts() async {
+  Future<String> resolve(String sdkSourcePath,
+      [String relativeSnapshotPath]) async {
+    String result = sdkRoot.resolve(sdkSourcePath).toFilePath();
+    if (_options.useSdk && relativeSnapshotPath != null) {
+      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');
+  _buildSdkScript = await resolve('pkg/dev_compiler/tool/build_sdk.dart');
+  _patchSdkScript = await resolve('pkg/dev_compiler/tool/patch_sdk.dart');
+  _sdkDevRuntime = await resolve('sdk/lib/_internal/js_dev_runtime');
+}
diff --git a/pkg/dev_compiler/test/nullable_inference_test.dart b/pkg/dev_compiler/test/nullable_inference_test.dart
index fe8f787..d79ce0b 100644
--- a/pkg/dev_compiler/test/nullable_inference_test.dart
+++ b/pkg/dev_compiler/test/nullable_inference_test.dart
@@ -43,7 +43,7 @@
     });
     test('Map', () async {
       await expectNotNull('main() { print({"x": null}); }',
-          '<dart.core::String*, dart.core::Null*>{"x": null}, "x"');
+          '<dart.core::String*, dart.core::Null?>{"x": null}, "x"');
     });
 
     test('Symbol', () async {
@@ -249,7 +249,7 @@
 
   test('function expression', () async {
     await expectNotNull('main() { () => null; f() {}; f; }',
-        '() → dart.core::Null* => null, f');
+        '() → dart.core::Null? => null, f');
   });
 
   test('cascades (kernel let)', () async {
@@ -391,7 +391,7 @@
         var x = () => 42;
         var y = (() => x = null);
       }''',
-          '() → dart.core::int* => 42, 42, () → dart.core::Null* => x = null');
+          '() → dart.core::int* => 42, 42, () → dart.core::Null? => x = null');
     });
     test('do not depend on unrelated variables', () async {
       await expectNotNull('''main() {
@@ -495,7 +495,19 @@
   var actualNotNull = collector.notNullExpressions
       // ConstantExpressions print the table offset - we want to compare
       // against the underlying constant value instead.
-      .map((e) => (e is ConstantExpression ? e.constant : e).toString())
+      .map((e) {
+        if (e is ConstantExpression) {
+          Constant c = e.constant;
+          if (c is DoubleConstant &&
+              c.value.isFinite &&
+              c.value.truncateToDouble() == c.value) {
+            // Print integer values as integers
+            return BigInt.from(c.value).toString();
+          }
+          return c.toString();
+        }
+        return e.toString();
+      })
       // Filter out our own NotNull annotations.  The library prefix changes
       // per test, so just filter on the suffix.
       .where((s) => !s.endsWith('::_NotNull {}'))
diff --git a/pkg/dev_compiler/tool/ddb b/pkg/dev_compiler/tool/ddb
index ff8e482..2a73fd9 100755
--- a/pkg/dev_compiler/tool/ddb
+++ b/pkg/dev_compiler/tool/ddb
@@ -25,7 +25,7 @@
   }
 
   // Parse flags.
-  var parser = new ArgParser()
+  var parser = ArgParser()
     ..addFlag('help', abbr: 'h', help: 'Display this message.')
     ..addFlag('kernel',
         abbr: 'k', help: 'Compile with the new kernel-based front end.')
@@ -37,6 +37,12 @@
         abbr: 'd',
         help: 'Use current source instead of built SDK.',
         defaultsTo: false)
+    ..addFlag('observe',
+        help:
+            'Run the compiler in the Dart VM with --observe. Implies --debug.',
+        defaultsTo: false)
+    ..addOption('vm-service-port',
+        help: 'Specify the observatory port. Implied --observe.')
     ..addFlag('summarize-text',
         help: 'Emit API summary in a .js.txt file.\n'
             'Ignored when not passed with --kernel.',
@@ -59,7 +65,7 @@
         defaultsTo: 'all');
 
   var options = parser.parse(args);
-  if (options['help']) {
+  if (options['help'] as bool) {
     printUsage();
     print('Available options:');
     print(parser.usage);
@@ -70,7 +76,9 @@
     printUsage();
     exit(1);
   }
-  var debug = options['debug'] as bool;
+  var debug = options['debug'] as bool ||
+      options['observe'] as bool ||
+      options.wasParsed('vm-service-port');
   var kernel = options['kernel'] as bool;
   var summarizeText = options['summarize-text'] as bool;
   var binary = options['binary'] as String;
@@ -106,35 +114,37 @@
   var ddcPath = p.dirname(p.dirname(toolPath));
   var dartCheckoutPath = p.dirname(p.dirname(ddcPath));
 
-  ProcessResult runDdc(String command, List<String> args) {
+  Future<void> runDdc(String command, List<String> args) async {
     if (debug) {
       // Use unbuilt script.  This only works from a source checkout.
-      args.insertAll(
-          0, ['--enable-asserts', p.join(ddcPath, 'bin', '$command.dart')]);
+      var vmServicePort = options.wasParsed('vm-service-port')
+          ? '=${options['vm-service-port']}'
+          : '';
+      var observe =
+          options.wasParsed('vm-service-port') || options['observe'] as bool;
+      args.insertAll(0, [
+        if (observe) ...[
+          '--enable-vm-service$vmServicePort',
+          '--pause-isolates-on-start',
+        ],
+        '--enable-asserts',
+        p.join(ddcPath, 'bin', '$command.dart')
+      ]);
       command = dartBinary;
     } else {
       // Use built snapshot.
       command = p.join(dartSdk, 'bin', command);
     }
-    return Process.runSync(command, args);
-  }
-
-  /// Writes stdout and stderr from [result] to this process.
-  ///
-  /// Will exit with the exit code from [result] when it's not zero.
-  void echoResult(ProcessResult result) async {
-    stdout.write(result.stdout);
-    await stdout.flush();
-    stderr.write(result.stderr);
-    await stderr.flush();
-    if (result.exitCode != 0) exit(result.exitCode);
+    var process =
+        await Process.start(command, args, mode: ProcessStartMode.inheritStdio);
+    if (await process.exitCode != 0) exit(await process.exitCode);
   }
 
   String mod;
   bool chrome = false;
   bool node = false;
   bool d8 = false;
-  switch (options['runtime']) {
+  switch (options['runtime'] as String) {
     case 'node':
       node = true;
       mod = 'common';
@@ -163,7 +173,6 @@
   ddcSdk = p.join(
       dartSdk, 'lib', '_internal', kernel ? 'ddc_sdk.dill' : 'ddc_sdk.sum');
 
-  ProcessResult result;
   if (compile) {
     var ddcArgs = [
       if (kernel) '--kernel',
@@ -181,8 +190,7 @@
       entry
     ];
 
-    result = runDdc('dartdevc', ddcArgs);
-    await echoResult(result);
+    await runDdc('dartdevc', ddcArgs);
   }
 
   if (run) {
@@ -219,16 +227,20 @@
 </script>
 ''';
       var htmlFile = p.setExtension(entry, '.html');
-      new File(htmlFile).writeAsStringSync(html);
+      File(htmlFile).writeAsStringSync(html);
       var tmp = p.join(Directory.systemTemp.path, 'ddc');
 
-      result = Process.runSync(chromeBinary, [
-        '--auto-open-devtools-for-tabs',
-        '--allow-file-access-from-files',
-        '--remote-debugging-port=$port',
-        '--user-data-dir=$tmp',
-        htmlFile
-      ]);
+      var process = await Process.start(
+          chromeBinary,
+          [
+            '--auto-open-devtools-for-tabs',
+            '--allow-file-access-from-files',
+            '--remote-debugging-port=$port',
+            '--user-data-dir=$tmp',
+            htmlFile
+          ],
+          mode: ProcessStartMode.inheritStdio);
+      if (await process.exitCode != 0) exit(await process.exitCode);
     } else if (node) {
       var nodePath = '$sdkJsPath:$libRoot';
       var runjs = '''
@@ -251,11 +263,13 @@
 }
 ''';
       var nodeFile = p.setExtension(entry, '.run.js');
-      new File(nodeFile).writeAsStringSync(runjs);
+      File(nodeFile).writeAsStringSync(runjs);
       var nodeBinary = binary ?? 'node';
-      result = Process.runSync(
+      var process = await Process.start(
           nodeBinary, ['--inspect=localhost:$port', nodeFile],
-          environment: {'NODE_PATH': nodePath});
+          environment: {'NODE_PATH': nodePath},
+          mode: ProcessStartMode.inheritStdio);
+      if (await process.exitCode != 0) exit(await process.exitCode);
     } else if (d8) {
       // Fix SDK import.  `d8` doesn't let us set paths, so we need a full path
       // to the SDK.
@@ -278,11 +292,12 @@
 }
 ''';
       var d8File = p.setExtension(entry, '.d8.js');
-      new File(d8File).writeAsStringSync(runjs);
+      File(d8File).writeAsStringSync(runjs);
       var d8Binary = binary ?? p.join(dartCheckoutPath, _d8executable);
-      result = Process.runSync(d8Binary, ['--module', d8File]);
+      var process = await Process.start(d8Binary, ['--module', d8File],
+          mode: ProcessStartMode.inheritStdio);
+      if (await process.exitCode != 0) exit(await process.exitCode);
     }
-    await echoResult(result);
   }
 }
 
@@ -294,5 +309,5 @@
   } else if (Platform.isMacOS) {
     return p.join('third_party', 'd8', 'macos', 'd8');
   }
-  throw new UnsupportedError('Unsupported platform.');
+  throw UnsupportedError('Unsupported platform.');
 }
diff --git a/pkg/dev_compiler/tool/kernel_sdk.dart b/pkg/dev_compiler/tool/kernel_sdk.dart
index 004097b..81eb813 100755
--- a/pkg/dev_compiler/tool/kernel_sdk.dart
+++ b/pkg/dev_compiler/tool/kernel_sdk.dart
@@ -7,6 +7,7 @@
 import 'dart:convert' show json;
 import 'dart:io';
 import 'package:args/args.dart' show ArgParser;
+import 'package:build_integration/file_system/multi_root.dart';
 import 'package:dev_compiler/src/compiler/module_builder.dart';
 import 'package:dev_compiler/src/compiler/shared_command.dart'
     show SharedCompilerOptions;
@@ -16,10 +17,11 @@
 import 'package:front_end/src/api_unstable/ddc.dart'
     show
         CompilerOptions,
-        kernelForModule,
         DiagnosticMessage,
-        printDiagnosticMessage,
-        Severity;
+        Severity,
+        StandardFileSystem,
+        kernelForModule,
+        printDiagnosticMessage;
 import 'package:kernel/kernel.dart';
 import 'package:kernel/target/targets.dart';
 import 'package:path/path.dart' as p;
@@ -55,17 +57,33 @@
     }
   }
 
+  String customScheme = "org-dartlang-sdk";
+  var fileSystem = MultiRootFileSystem(
+      customScheme, [Uri.base], StandardFileSystem.instance);
+  Uri sdkRoot = Uri.parse("$customScheme:/");
+  Uri packagesFileUri = sdkRoot
+      .resolve(p.relative(Uri.file(packagesPath).path, from: Uri.base.path));
+  if (packagesFileUri.scheme != customScheme) {
+    throw "packagesPath has to be under ${Uri.base}";
+  }
+  Uri librariesSpecificationUri = sdkRoot
+      .resolve(p.relative(Uri.file(librarySpecPath).path, from: Uri.base.path));
+  if (librariesSpecificationUri.scheme != customScheme) {
+    throw "librarySpecPath has to be under ${Uri.base}";
+  }
+
   var options = CompilerOptions()
     ..compileSdk = true
-    // TODO(sigmund): remove these two unnecessary options when possible.
-    ..sdkRoot = Uri.base
-    ..packagesFileUri = Uri.base.resolveUri(Uri.file(packagesPath))
-    ..librariesSpecificationUri = Uri.base.resolveUri(Uri.file(librarySpecPath))
+    ..fileSystem = fileSystem
+    ..sdkRoot = sdkRoot
+    ..packagesFileUri = packagesFileUri
+    ..librariesSpecificationUri = librariesSpecificationUri
     ..target = target
     ..onDiagnostic = onDiagnostic
     ..environmentDefines = {};
 
   var inputs = target.extraRequiredLibraries.map(Uri.parse).toList();
+
   var compilerResult = await kernelForModule(inputs, options);
   var component = compilerResult.component;
 
@@ -92,7 +110,10 @@
     var mapPath = '$jsPath.map';
     await Directory(jsDir).create();
     var jsCode = jsProgramToCode(jsModule, format,
-        jsUrl: jsPath, mapUrl: mapPath, buildSourceMap: true);
+        jsUrl: jsPath,
+        mapUrl: mapPath,
+        buildSourceMap: true,
+        customScheme: customScheme);
     await File(jsPath).writeAsString(jsCode.code);
     await File(mapPath).writeAsString(json.encode(jsCode.sourceMap));
   }
diff --git a/pkg/dev_compiler/tool/patch_sdk.dart b/pkg/dev_compiler/tool/patch_sdk.dart
index 5b268a8..543e90d 100755
--- a/pkg/dev_compiler/tool/patch_sdk.dart
+++ b/pkg/dev_compiler/tool/patch_sdk.dart
@@ -34,11 +34,16 @@
     exit(1);
   }
 
+  var sdk = 'sdk';
+  if (argv.length > 3) {
+    sdk = argv[3];
+  }
+
   var selfModifyTime = File(self).lastModifiedSync().millisecondsSinceEpoch;
 
   var repoDir = argv[0];
   var patchDir = argv[1];
-  var sdkLibIn = p.join(repoDir, 'sdk', 'lib');
+  var sdkLibIn = p.join(repoDir, sdk, 'lib');
   var patchIn = p.join(patchDir, 'patch');
   var privateIn = p.join(patchDir, 'private');
   var sdkOut = p.join(argv[2], 'lib');
diff --git a/pkg/expect/lib/expect.dart b/pkg/expect/lib/expect.dart
index 954a653..9d1d5ea 100644
--- a/pkg/expect/lib/expect.dart
+++ b/pkg/expect/lib/expect.dart
@@ -540,10 +540,11 @@
    */
   static void throws<T>(void f(),
       [bool check(T error) = _defaultCheck, String reason = ""]) {
-    // TODO(vsm): Make check nullable.  Existing tests pass null to set
-    // a reason.
-    check = check ?? _defaultCheck;
-    reason = reason ?? "";
+    // TODO(vsm): Make check and reason nullable or change call sites.
+    // Existing tests pass null to set a reason and/or pass them through
+    // via helpers.
+    check ??= _defaultCheck;
+    reason ??= "";
     String msg = reason.isEmpty ? "" : "($reason)";
     if (f is! Function()) {
       // Only throws from executing the function body should count as throwing.
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 c2c76e5..301536d 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -110,9 +110,6 @@
   @deprecated
   bool chaseDependencies;
 
-  /// True if enabling legacy mode (Dart 1 compatibility).
-  bool legacyMode = false;
-
   /// Patch files to apply on the core libraries for a specific target platform.
   ///
   /// Keys in the map are the name of the library with no `dart:` prefix, for
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
index 1c72931..052e2dd 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
@@ -15,6 +15,7 @@
   setLiterals,
   spreadCollections,
   tripleShift,
+  variance,
 }
 
 ExperimentalFlag parseExperimentalFlag(String flag) {
@@ -33,6 +34,8 @@
       return ExperimentalFlag.spreadCollections;
     case "triple-shift":
       return ExperimentalFlag.tripleShift;
+    case "variance":
+      return ExperimentalFlag.variance;
   }
   return null;
 }
@@ -45,6 +48,7 @@
   ExperimentalFlag.setLiterals: true,
   ExperimentalFlag.spreadCollections: true,
   ExperimentalFlag.tripleShift: false,
+  ExperimentalFlag.variance: false,
 };
 
 const Map<ExperimentalFlag, bool> expiredExperimentalFlags = {
@@ -55,4 +59,5 @@
   ExperimentalFlag.setLiterals: true,
   ExperimentalFlag.spreadCollections: true,
   ExperimentalFlag.tripleShift: false,
+  ExperimentalFlag.variance: false,
 };
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index 860f99f..fd6e8f0 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart
@@ -132,7 +132,6 @@
 
   CompilerOptions options = new CompilerOptions()
     ..target = target
-    ..legacyMode = target.legacyMode
     ..linkedDependencies = linkedDependencies
     ..librariesSpecificationUri = librariesSpecificationUri
     ..packagesFileUri = packagesFileUri
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 1f89337..28c54a7 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -298,8 +298,6 @@
   /// effect.
   void clearFileSystemCache() => _fileSystem = null;
 
-  bool get legacyMode => _raw.legacyMode;
-
   /// Whether to generate bytecode.
   bool get bytecode => _raw.bytecode;
 
@@ -312,8 +310,8 @@
   String get currentSdkVersion => _raw.currentSdkVersion;
 
   Target _target;
-  Target get target => _target ??=
-      _raw.target ?? new NoneTarget(new TargetFlags(legacyMode: legacyMode));
+  Target get target =>
+      _target ??= _raw.target ?? new NoneTarget(new TargetFlags());
 
   bool isExperimentEnabled(ExperimentalFlag flag) {
     assert(defaultExperimentalFlags.containsKey(flag),
@@ -646,7 +644,6 @@
         '(provided: ${_raw.librariesSpecificationUri})');
     sb.writeln('SDK summary: ${_sdkSummary} (provided: ${_raw.sdkSummary})');
 
-    sb.writeln('Legacy mode: ${legacyMode}');
     sb.writeln('Target: ${_target?.name} (provided: ${_raw.target?.name})');
 
     sb.writeln('throwOnErrorsForDebugging: ${throwOnErrorsForDebugging}');
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 481328b..1687f79 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -44,6 +44,7 @@
 
 import 'package:kernel/src/bounds_checks.dart'
     show TypeArgumentIssue, findTypeArgumentIssues, getGenericTypeName;
+import 'package:kernel/text/text_serialization_verifier.dart';
 
 import 'package:kernel/type_algebra.dart' show Substitution, substitute;
 
@@ -390,6 +391,10 @@
   /// For a patch class the origin class is returned.
   Class get cls;
 
+  InterfaceType _legacyRawType;
+  InterfaceType _nullableRawType;
+  InterfaceType _nonNullableRawType;
+
   // Deliberately unrelated return type to statically detect more accidental
   // use until Builder.target is fully retired.
   UnrelatedTarget get target => unsupported(
@@ -406,12 +411,50 @@
   @override
   InterfaceType get thisType => cls.thisType;
 
+  InterfaceType get legacyRawType {
+    // TODO(dmitryas): Use computeBound instead of DynamicType here?
+    return _legacyRawType ??= new InterfaceType(
+        cls,
+        new List<DartType>.filled(typeVariablesCount, const DynamicType()),
+        Nullability.legacy);
+  }
+
+  InterfaceType get nullableRawType {
+    // TODO(dmitryas): Use computeBound instead of DynamicType here?
+    return _nullableRawType ??= new InterfaceType(
+        cls,
+        new List<DartType>.filled(typeVariablesCount, const DynamicType()),
+        Nullability.nullable);
+  }
+
+  InterfaceType get nonNullableRawType {
+    // TODO(dmitryas): Use computeBound instead of DynamicType here?
+    return _nonNullableRawType ??= new InterfaceType(
+        cls,
+        new List<DartType>.filled(typeVariablesCount, const DynamicType()),
+        Nullability.nonNullable);
+  }
+
+  InterfaceType rawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return legacyRawType;
+      case Nullability.nullable:
+        return nullableRawType;
+      case Nullability.nonNullable:
+        return nonNullableRawType;
+      case Nullability.neither:
+      default:
+        return unhandled("$nullability", "rawType", noOffset, noUri);
+    }
+  }
+
   /// [arguments] have already been built.
   InterfaceType buildTypesWithBuiltArguments(LibraryBuilder library,
       Nullability nullability, List<DartType> arguments) {
     assert(arguments == null || cls.typeParameters.length == arguments.length);
     return arguments == null
-        ? cls.rawType
+        ? rawType(nullability)
         : new InterfaceType(cls, arguments, nullability);
   }
 
@@ -436,11 +479,11 @@
       return result;
     }
 
-    if (arguments != null && arguments.length != (typeVariables?.length ?? 0)) {
+    if (arguments != null && arguments.length != typeVariablesCount) {
       // That should be caught and reported as a compile-time error earlier.
       return unhandled(
           templateTypeArgumentMismatch
-              .withArguments(typeVariables.length)
+              .withArguments(typeVariablesCount)
               .message,
           "buildTypeArguments",
           -1,
@@ -1040,8 +1083,7 @@
                         interfaceMember.fileOffset, noLength)
               ] +
               inheritedContext(isInterfaceCheck, declaredMember));
-    } else if (!library.loader.target.backendTarget.legacyMode &&
-        declaredFunction?.typeParameters != null) {
+    } else if (declaredFunction?.typeParameters != null) {
       Map<TypeParameter, DartType> substitutionMap =
           <TypeParameter, DartType>{};
       for (int i = 0; i < declaredFunction.typeParameters.length; ++i) {
@@ -1109,8 +1151,6 @@
       VariableDeclaration declaredParameter,
       bool isInterfaceCheck,
       {bool asIfDeclaredParameter = false}) {
-    if (library.loader.target.backendTarget.legacyMode) return;
-
     if (interfaceSubstitution != null) {
       interfaceType = interfaceSubstitution.substituteType(interfaceType);
     }
@@ -1619,7 +1659,7 @@
     // its enclosing class, because constructors cannot specify type parameters
     // of their own.
     FunctionType factoryType =
-        factory.procedure.function.functionType.withoutTypeParameters;
+        factory.procedure.function.thisFunctionType.withoutTypeParameters;
     FunctionType redirecteeType =
         computeRedirecteeType(factory, typeEnvironment);
 
diff --git a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
index dcb82cb..df6cd20 100644
--- a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
@@ -265,8 +265,7 @@
 
   InterfaceType buildType(LibraryBuilder library, Nullability nullability,
       List<TypeBuilder> arguments) {
-    // TODO(dmitryas): Use [nullability].
-    return cls.rawType;
+    return rawType(nullability);
   }
 
   @override
@@ -300,8 +299,8 @@
     }
     FieldBuilder valuesBuilder = firstMemberNamed("values");
     valuesBuilder.build(libraryBuilder);
-    valuesBuilder.initializer =
-        new ListLiteral(values, typeArgument: cls.rawType, isConst: true);
+    valuesBuilder.initializer = new ListLiteral(values,
+        typeArgument: rawType(library.nonNullable), isConst: true);
     ConstructorBuilder constructorBuilder = constructorScopeBuilder[""];
     Constructor constructor = constructorBuilder.build(libraryBuilder);
     constructor.initializers.insert(
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 44bba27..6ef5385 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -91,9 +91,7 @@
   }
 
   bool get isEligibleForInference {
-    return !library.legacyMode &&
-        type == null &&
-        (hasInitializer || isClassInstanceMember);
+    return type == null && (hasInitializer || isClassInstanceMember);
   }
 
   Field build(SourceLibraryBuilder libraryBuilder) {
@@ -167,7 +165,7 @@
           .createBodyBuilderForOutlineExpression(
               library, classBuilder, this, scope, fileUri);
       bodyBuilder.constantContext =
-          isConst ? ConstantContext.inferred : ConstantContext.none;
+          isConst ? ConstantContext.inferred : ConstantContext.required;
       initializer = bodyBuilder.parseFieldInitializer(constInitializerToken)
         ..parent = field;
       bodyBuilder.typeInferrer
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 4e7e8c3..3083665 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
@@ -41,7 +41,7 @@
         MetadataBuilder,
         TypeBuilder;
 
-import '../kernel/kernel_shadow_ast.dart' show VariableDeclarationJudgment;
+import '../kernel/kernel_shadow_ast.dart' show VariableDeclarationImpl;
 
 /// A builder for a formal parameter, i.e. a parameter on a method or
 /// constructor.
@@ -99,7 +99,7 @@
   VariableDeclaration build(
       SourceLibraryBuilder library, int functionNestingLevel) {
     if (variable == null) {
-      variable = new VariableDeclarationJudgment(name, functionNestingLevel,
+      variable = new VariableDeclarationImpl(name, functionNestingLevel,
           type: type?.build(library),
           isFinal: isFinal,
           isConst: isConst,
diff --git a/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
index 16c1282..f591207 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
@@ -4,7 +4,8 @@
 
 library fasta.function_type_builder;
 
-import 'builder.dart' show LibraryBuilder, TypeBuilder, TypeVariableBuilder;
+import 'builder.dart'
+    show LibraryBuilder, NullabilityBuilder, TypeBuilder, TypeVariableBuilder;
 
 import 'package:kernel/ast.dart'
     show
@@ -32,8 +33,10 @@
   final TypeBuilder returnType;
   final List<TypeVariableBuilder> typeVariables;
   final List<FormalParameterBuilder> formals;
+  final NullabilityBuilder nullabilityBuilder;
 
-  FunctionTypeBuilder(this.returnType, this.typeVariables, this.formals);
+  FunctionTypeBuilder(this.returnType, this.typeVariables, this.formals,
+      this.nullabilityBuilder);
 
   @override
   String get name => null;
@@ -68,7 +71,9 @@
         buffer.write(t?.fullNameForErrors);
       }
     }
-    buffer.write(") -> ");
+    buffer.write(") ->");
+    nullabilityBuilder.writeNullabilityOn(buffer);
+    buffer.write(" ");
     buffer.write(returnType?.fullNameForErrors);
     return buffer;
   }
@@ -106,7 +111,8 @@
         namedParameters: namedParameters ?? const <NamedType>[],
         typeParameters: typeParameters ?? const <TypeParameter>[],
         requiredParameterCount: requiredParameterCount,
-        typedefType: origin);
+        typedefType: origin,
+        nullability: nullabilityBuilder.build(library));
   }
 
   Supertype buildSupertype(
@@ -143,7 +149,10 @@
       }
     }
     FunctionTypeBuilder newType = new FunctionTypeBuilder(
-        returnType?.clone(newTypes), clonedTypeVariables, clonedFormals);
+        returnType?.clone(newTypes),
+        clonedTypeVariables,
+        clonedFormals,
+        nullabilityBuilder);
     newTypes.add(newType);
     return newType;
   }
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 44d9beb..27f7bbf 100644
--- a/pkg/front_end/lib/src/fasta/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
@@ -4,7 +4,7 @@
 
 library fasta.library_builder;
 
-import 'package:kernel/ast.dart' show Library;
+import 'package:kernel/ast.dart' show Library, Nullability;
 
 import '../combinator.dart' show Combinator;
 
@@ -60,8 +60,6 @@
         exportScopeBuilder = new ScopeBuilder(exportScope),
         super(null, -1, fileUri);
 
-  bool get legacyMode => false;
-
   bool get isSynthetic => false;
 
   // Deliberately unrelated return type to statically detect more accidental
@@ -274,9 +272,26 @@
 
   List<FieldBuilder> takeImplicitlyTypedFields() => null;
 
-  // TODO(dmitryas): Compute the predicate using the library version instead.
+  // TODO(38287): Compute the predicate using the library version instead.
   bool get isNonNullableByDefault => loader.target.enableNonNullable;
 
+  Nullability get nullable {
+    return isNonNullableByDefault ? Nullability.nullable : Nullability.legacy;
+  }
+
+  Nullability get nonNullable {
+    return isNonNullableByDefault
+        ? Nullability.nonNullable
+        : Nullability.legacy;
+  }
+
+  Nullability nullableIfTrue(bool isNullable) {
+    if (isNonNullableByDefault) {
+      return isNullable ? Nullability.nullable : Nullability.nonNullable;
+    }
+    return Nullability.legacy;
+  }
+
   NullabilityBuilder computeNullabilityFromToken(bool markedAsNullable) {
     if (!isNonNullableByDefault) {
       return const NullabilityBuilder.legacy();
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 dbe2ed7..4f67b7c 100644
--- a/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart
@@ -35,6 +35,19 @@
   const NullabilityBuilder.omitted()
       : _syntacticNullability = SyntacticNullability.omitted;
 
+  factory NullabilityBuilder.fromNullability(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.nullable:
+        return const NullabilityBuilder.nullable();
+      case Nullability.legacy:
+        return const NullabilityBuilder.legacy();
+      case Nullability.nonNullable:
+      case Nullability.neither:
+      default:
+        return const NullabilityBuilder.omitted();
+    }
+  }
+
   /// Used temporarily in the places that need proper handling of NNBD features.
   ///
   /// Over time the uses of [NullabilityBuilder.pendingImplementation] should be
@@ -42,7 +55,7 @@
   /// it redirects to [NullabilityBuilder.legacy] as a conservative safety
   /// measure for the pre-NNBD code and as a visible reminder of the feature
   /// implementation being in progress in the NNBD code.
-  // TODO(dmitryas): Remove this constructor.
+  // TODO(38286): Remove this constructor.
   const NullabilityBuilder.pendingImplementation() : this.legacy();
 
   Nullability build(LibraryBuilder libraryBuilder, {Nullability ifOmitted}) {
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 e39c9c2..bf45b08 100644
--- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
@@ -45,7 +45,7 @@
         TypeVariableBuilder,
         isRedirectingGenerativeConstructorImplementation;
 
-import '../kernel/kernel_shadow_ast.dart' show VariableDeclarationJudgment;
+import '../kernel/kernel_shadow_ast.dart' show VariableDeclarationImpl;
 
 import '../kernel/redirecting_factory_body.dart' show RedirectingFactoryBody;
 
@@ -301,7 +301,7 @@
       // Do this after building the parameters, since the diet listener
       // assumes that parameters are built, even if illegal in number.
       VariableDeclaration parameter =
-          new VariableDeclarationJudgment("#synthetic", 0);
+          new VariableDeclarationImpl("#synthetic", 0);
       result.positionalParameters.clear();
       result.positionalParameters.add(parameter);
       parameter.parent = result;
@@ -515,7 +515,7 @@
       List<Statement> statements = [];
       Block block = new Block(statements);
       VariableDeclaration variableDeclaration =
-          new VariableDeclarationJudgment.forValue(
+          new VariableDeclarationImpl.forValue(
               new VariableGet(value)..fileOffset = procedure.fileOffset)
             ..type = value.type;
       statements.add(variableDeclaration);
@@ -549,7 +549,6 @@
   }
 
   bool get isEligibleForTopLevelInference {
-    if (library.legacyMode) return false;
     if (isDeclarationInstanceMember) {
       if (returnType == null) return true;
       if (formals != null) {
@@ -864,7 +863,6 @@
   }
 
   bool get isEligibleForTopLevelInference {
-    if (library.legacyMode) return false;
     if (formals != null) {
       for (FormalParameterBuilder formal in formals) {
         if (formal.type == null && formal.isInitializingFormal) return true;
@@ -907,7 +905,7 @@
       BodyBuilder bodyBuilder = library.loader
           .createBodyBuilderForOutlineExpression(
               library, classBuilder, this, classBuilder.scope, fileUri);
-      bodyBuilder.constantContext = ConstantContext.inferred;
+      bodyBuilder.constantContext = ConstantContext.required;
       bodyBuilder.parseInitializers(beginInitializers);
       bodyBuilder.resolveRedirectingFactoryTargets();
     }
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 8aad521..3b00c71 100644
--- a/pkg/front_end/lib/src/fasta/command_line_reporting.dart
+++ b/pkg/front_end/lib/src/fasta/command_line_reporting.dart
@@ -180,7 +180,7 @@
       return true;
 
     case Severity.errorLegacyWarning:
-      return !CompilerContext.current.options.legacyMode;
+      return true;
 
     case Severity.warning:
     case Severity.context:
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 56c203ae..e227553 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
@@ -96,8 +96,6 @@
   /// [../kernel/kernel_library_builder.dart].
   Map<String, String> unserializableExports;
 
-  bool exportsAlreadyFinalized = false;
-
   // TODO(jensj): These 4 booleans could potentially be merged into a single
   // state field.
   bool isReadyToBuild = false;
@@ -116,6 +114,11 @@
 
   void ensureLoaded() {
     if (!isReadyToBuild) throw new StateError("Not ready to build.");
+    if (isBuilt && !isBuiltAndMarked) {
+      isBuiltAndMarked = true;
+      finalizeExports();
+      return;
+    }
     isBuiltAndMarked = true;
     if (isBuilt) return;
     isBuilt = true;
@@ -251,8 +254,6 @@
   }
 
   void finalizeExports() {
-    if (exportsAlreadyFinalized) return;
-    exportsAlreadyFinalized = true;
     unserializableExports?.forEach((String name, String messageText) {
       Builder declaration;
       switch (name) {
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index d5482bf..a2a2622 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -5806,30 +5806,6 @@
         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)>
-    templateInternalProblemNoInferredTypeStored =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""There's no inferred type for '#name'.""",
-        withArguments: _withArgumentsInternalProblemNoInferredTypeStored);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    codeInternalProblemNoInferredTypeStored =
-    const Code<Message Function(String name)>(
-        "InternalProblemNoInferredTypeStored",
-        templateInternalProblemNoInferredTypeStored,
-        severity: Severity.internalProblem);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInternalProblemNoInferredTypeStored(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeInternalProblemNoInferredTypeStored,
-      message: """There's no inferred type for '${name}'.""",
-      arguments: {'name': name});
-}
-
-// 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'.""",
@@ -5944,38 +5920,6 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(DartType _type, String name)>
-    templateInternalProblemStoringMultipleInferredTypes =
-    const Template<Message Function(DartType _type, String name)>(
-        messageTemplate:
-            r"""There's already an inferred type, '#type', for '#name'.""",
-        withArguments:
-            _withArgumentsInternalProblemStoringMultipleInferredTypes);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, String name)>
-    codeInternalProblemStoringMultipleInferredTypes =
-    const Code<Message Function(DartType _type, String name)>(
-        "InternalProblemStoringMultipleInferredTypes",
-        templateInternalProblemStoringMultipleInferredTypes,
-        severity: Severity.internalProblem);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInternalProblemStoringMultipleInferredTypes(
-    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(codeInternalProblemStoringMultipleInferredTypes,
-      message:
-          """There's already an inferred type, '${type}', for '${name}'.""" +
-              labeler.originMessages,
-      arguments: {'type': _type, 'name': name});
-}
-
-// 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)>(
@@ -6982,6 +6926,16 @@
         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)>(
@@ -7731,6 +7685,19 @@
 }
 
 // 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.
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
index 202fd66..aa2b361 100644
--- a/pkg/front_end/lib/src/fasta/flow_analysis/flow_analysis.dart
+++ b/pkg/front_end/lib/src/fasta/flow_analysis/flow_analysis.dart
@@ -407,10 +407,15 @@
   /// - Call [forEach_end].
   ///
   /// [loopAssigned] should be the set of variables that are assigned anywhere
-  /// in the loop's body.
-  void forEach_bodyBegin(Set<Variable> loopAssigned) {
+  /// in the loop's body.  [loopVariable] should be the loop variable, if it's a
+  /// local variable, or `null` otherwise.
+  void forEach_bodyBegin(Set<Variable> loopAssigned, Variable loopVariable) {
     _stack.add(_current);
     _current = _current.removePromotedAll(loopAssigned, _referencedVariables);
+    if (loopVariable != null) {
+      assert(loopAssigned.contains(loopVariable));
+      _current = _current.write(typeOperations, loopVariable);
+    }
   }
 
   /// Call this method just before visiting the body of a "for-in" statement or
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 1288b94..43af7e5 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -6,6 +6,9 @@
 
 import 'dart:async' show Future;
 
+import 'package:front_end/src/fasta/dill/dill_class_builder.dart'
+    show DillClassBuilder;
+
 import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
 
 import 'package:kernel/binary/ast_from_binary.dart'
@@ -48,7 +51,7 @@
 
 import '../api_prototype/memory_file_system.dart' show MemoryFileSystem;
 
-import 'builder/builder.dart' show ClassBuilder, LibraryBuilder;
+import 'builder/builder.dart' show Builder, ClassBuilder, LibraryBuilder;
 
 import 'builder_graph.dart' show BuilderGraph;
 
@@ -74,7 +77,7 @@
 
 import 'kernel/kernel_builder.dart' show ClassHierarchyBuilder;
 
-import 'kernel/kernel_shadow_ast.dart' show VariableDeclarationJudgment;
+import 'kernel/kernel_shadow_ast.dart' show VariableDeclarationImpl;
 
 import 'kernel/kernel_target.dart' show KernelTarget;
 
@@ -311,7 +314,17 @@
         // Reset dill loaders and kernel class hierarchy.
         for (LibraryBuilder builder in dillLoadedData.loader.builders.values) {
           if (builder is DillLibraryBuilder) {
-            builder.isBuiltAndMarked = false;
+            if (builder.isBuiltAndMarked) {
+              // Clear cached calculations in classes which upon calculation can
+              // mark things as needed.
+              for (Builder builder in builder.scope.local.values) {
+                if (builder is DillClassBuilder) {
+                  builder.supertype = null;
+                  builder.interfaces = null;
+                }
+              }
+              builder.isBuiltAndMarked = false;
+            }
           }
         }
 
@@ -717,7 +730,8 @@
     if (summaryBytes != null) {
       ticker.logMs("Read ${c.options.sdkSummary}");
       data.component = c.options.target.configureComponent(new Component());
-      new BinaryBuilder(summaryBytes, disableLazyReading: false)
+      new BinaryBuilder(summaryBytes,
+              disableLazyReading: false, disableLazyClassReading: true)
           .readComponent(data.component);
       ticker.logMs("Deserialized ${c.options.sdkSummary}");
       bytesLength += summaryBytes.length;
@@ -905,7 +919,7 @@
       FunctionNode parameters = new FunctionNode(null,
           typeParameters: typeDefinitions,
           positionalParameters: definitions.keys
-              .map((name) => new VariableDeclarationJudgment(name, 0))
+              .map((name) => new VariableDeclarationImpl(name, 0))
               .toList());
 
       debugLibrary.build(userCode.loader.coreLibrary, modifyTarget: false);
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 e9bb860..8a82cd2 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,8 @@
 
 import 'dart:core' hide MapEntry;
 
+import 'package:kernel/ast.dart';
+
 import '../builder/declaration_builder.dart';
 
 import '../constant_context.dart' show ConstantContext;
@@ -169,9 +171,6 @@
   @override
   final TypePromoter typePromoter;
 
-  @override
-  final bool legacyMode;
-
   /// Only used when [member] is a constructor. It tracks if an implicit super
   /// initializer is needed.
   ///
@@ -290,7 +289,6 @@
         needsImplicitSuperInitializer = declarationBuilder is ClassBuilder &&
             coreTypes?.objectClass != declarationBuilder.cls,
         typePromoter = typeInferrer?.typePromoter,
-        legacyMode = libraryBuilder.legacyMode,
         super(enclosingScope);
 
   BodyBuilder.withParents(FieldBuilder field, SourceLibraryBuilder part,
@@ -349,8 +347,7 @@
 
   TypeEnvironment get typeEnvironment => typeInferrer?.typeSchemaEnvironment;
 
-  DartType get implicitTypeArgument =>
-      legacyMode ? const DynamicType() : const ImplicitTypeArgument();
+  DartType get implicitTypeArgument => const ImplicitTypeArgument();
 
   @override
   void push(Object node) {
@@ -818,15 +815,7 @@
 
     // For async, async*, and sync* functions with declared return types, we
     // need to determine whether those types are valid.
-    // TODO(hillerstrom): currently, we need to check whether [legacyMode] is
-    // enabled for two reasons:
-    // 1) the [isSubtypeOf] predicate produces false-negatives when
-    // [legacyMode] is enabled.
-    // 2) the member [typeEnvironment] might be null when [legacyMode] is
-    // enabled.
-    // This particular behavior can be observed when running the fasta perf
-    // benchmarks.
-    if (!legacyMode && builder.returnType != null) {
+    if (builder.returnType != null) {
       DartType returnType = builder.function.returnType;
       // We use the same trick in each case below. For example to decide whether
       // Future<T> <: [returnType] for every T, we rely on Future<Bot> and
@@ -926,9 +915,8 @@
     } else {
       if (body != null) {
         builder.body = new Block(<Statement>[
-          new ExpressionStatementJudgment(desugarSyntheticExpression(
-              buildProblem(fasta.messageExternalMethodWithBody, body.fileOffset,
-                  noLength)))
+          new ExpressionStatement(desugarSyntheticExpression(buildProblem(
+              fasta.messageExternalMethodWithBody, body.fileOffset, noLength)))
             ..fileOffset = body.fileOffset,
           body,
         ])
@@ -997,7 +985,7 @@
       if (invocation.parent == null) continue;
       if (typeInferrer != null) {
         if (invocation is FactoryConstructorInvocationJudgment &&
-            invocation.inferredType == null) {
+            !invocation.hasBeenInferred) {
           continue;
         }
       } else {
@@ -1012,7 +1000,7 @@
       Expression replacementNode;
 
       RedirectionTarget redirectionTarget =
-          getRedirectionTarget(initialTarget, this, legacyMode: legacyMode);
+          getRedirectionTarget(initialTarget, this);
       Member resolvedTarget = redirectionTarget?.target;
 
       if (resolvedTarget == null) {
@@ -1209,7 +1197,7 @@
               .withLocation(uri, eof.charOffset, eof.length));
     }
 
-    ReturnJudgment fakeReturn = new ReturnJudgment(true, expression);
+    ReturnStatementImpl fakeReturn = new ReturnStatementImpl(true, expression);
 
     typeInferrer?.inferFunctionBody(
         this, const DynamicType(), AsyncMarker.Sync, fakeReturn);
@@ -1431,14 +1419,14 @@
   void beginCascade(Token token) {
     debugEvent("beginCascade");
     Expression expression = popForValue();
-    if (expression is CascadeJudgment) {
+    if (expression is Cascade) {
       push(expression);
       push(new VariableUseGenerator(this, token, expression.variable));
       expression.extend();
     } else {
       VariableDeclaration variable = forest.createVariableDeclarationForValue(
           expression.fileOffset, expression);
-      push(new CascadeJudgment(variable)..fileOffset = expression.fileOffset);
+      push(new Cascade(variable)..fileOffset = expression.fileOffset);
       push(new VariableUseGenerator(this, token, variable));
     }
   }
@@ -1447,7 +1435,7 @@
   void endCascade() {
     debugEvent("endCascade");
     Expression expression = popForEffect();
-    CascadeJudgment cascadeReceiver = pop();
+    Cascade cascadeReceiver = pop();
     cascadeReceiver.finalize(expression);
     push(cascadeReceiver);
   }
@@ -1631,20 +1619,6 @@
             .withLocation(uri, charOffset, length);
       }
     }
-    if (legacyMode && constantContext == ConstantContext.none) {
-      addProblem(message.messageObject, message.charOffset, message.length,
-          wasHandled: true, context: context);
-      return forest.createThrow(
-          null,
-          libraryBuilder.loader.instantiateNoSuchMethodError(
-              receiver, name, arguments, charOffset,
-              isMethod: !isGetter && !isSetter,
-              isGetter: isGetter,
-              isSetter: isSetter,
-              isStatic: isStatic,
-              isTopLevel: !isStatic && !isSuper))
-        ..fileOffset = charOffset;
-    }
     return desugarSyntheticExpression(buildProblem(
         message.messageObject, message.charOffset, message.length,
         context: context));
@@ -1774,8 +1748,7 @@
     Object fact =
         typePromoter?.getFactForAccess(variable, functionNestingLevel);
     Object scope = typePromoter?.currentScope;
-    return new VariableGetJudgment(variable, fact, scope)
-      ..fileOffset = charOffset;
+    return new VariableGetImpl(variable, fact, scope)..fileOffset = charOffset;
   }
 
   /// Helper method to create a [ReadOnlyAccessGenerator] on the [variable]
@@ -2072,15 +2045,6 @@
   void handleLiteralInt(Token token) {
     debugEvent("LiteralInt");
     int value = int.tryParse(token.lexeme);
-    if (legacyMode) {
-      if (value == null) {
-        push(unhandled(
-            'large integer', 'handleLiteralInt', token.charOffset, uri));
-      } else {
-        push(forest.createIntLiteral(value, token));
-      }
-      return;
-    }
     // Postpone parsing of literals resulting in a negative value
     // (hex literals >= 2^63). These are only allowed when not negated.
     if (value == null || value < 0) {
@@ -2186,7 +2150,7 @@
     bool isFinal = (currentLocalVariableModifiers & finalMask) != 0;
     bool isLate = (currentLocalVariableModifiers & lateMask) != 0;
     assert(isConst == (constantContext == ConstantContext.inferred));
-    VariableDeclaration variable = new VariableDeclarationJudgment(
+    VariableDeclaration variable = new VariableDeclarationImpl(
         identifier.name, functionNestingLevel,
         forSyntheticToken: deprecated_extractToken(identifier).isSynthetic,
         initializer: initializer,
@@ -2362,12 +2326,12 @@
     if (variableOrExpression is VariableDeclaration) {
       return <VariableDeclaration>[variableOrExpression];
     } else if (variableOrExpression is Expression) {
-      VariableDeclaration variable = new VariableDeclarationJudgment.forEffect(
-          variableOrExpression, functionNestingLevel);
+      VariableDeclaration variable =
+          new VariableDeclarationImpl.forEffect(variableOrExpression);
       return <VariableDeclaration>[variable];
     } else if (variableOrExpression is ExpressionStatement) {
-      VariableDeclaration variable = new VariableDeclarationJudgment.forEffect(
-          variableOrExpression.expression, functionNestingLevel);
+      VariableDeclaration variable = new VariableDeclarationImpl.forEffect(
+          variableOrExpression.expression);
       return <VariableDeclaration>[variable];
     } else if (forest.isVariablesDeclaration(variableOrExpression)) {
       return forest
@@ -2527,6 +2491,11 @@
       int count, Token leftBracket, Token constKeyword, Token rightBracket) {
     debugEvent("LiteralList");
 
+    if (constantContext == ConstantContext.required && constKeyword == null) {
+      addProblem(fasta.messageMissingExplicitConst, offsetForToken(leftBracket),
+          noLength);
+    }
+
     // TODO(danrubel): Replace this with popListForValue
     // when control flow and spread collections have been enabled by default
     List<Expression> expressions =
@@ -2552,10 +2521,7 @@
         typeArgument = const InvalidType();
       } else {
         typeArgument = buildDartType(typeArguments.single);
-        if (!legacyMode) {
-          typeArgument =
-              instantiateToBounds(typeArgument, coreTypes.objectClass);
-        }
+        typeArgument = instantiateToBounds(typeArgument, coreTypes.objectClass);
       }
     } else {
       typeArgument = implicitTypeArgument;
@@ -2578,9 +2544,7 @@
     DartType typeArgument;
     if (typeArguments != null) {
       typeArgument = buildDartType(typeArguments.single);
-      if (!libraryBuilder.loader.target.legacyMode) {
-        typeArgument = instantiateToBounds(typeArgument, coreTypes.objectClass);
-      }
+      typeArgument = instantiateToBounds(typeArgument, coreTypes.objectClass);
     } else {
       typeArgument = implicitTypeArgument;
     }
@@ -2624,6 +2588,11 @@
   ) {
     debugEvent("LiteralSetOrMap");
 
+    if (constantContext == ConstantContext.required && constKeyword == null) {
+      addProblem(fasta.messageMissingExplicitConst, offsetForToken(leftBrace),
+          noLength);
+    }
+
     List<dynamic> setOrMapEntries =
         new List<dynamic>.filled(count, null, growable: true);
     for (int i = count - 1; i >= 0; i--) {
@@ -2708,10 +2677,8 @@
       } else {
         keyType = buildDartType(typeArguments[0]);
         valueType = buildDartType(typeArguments[1]);
-        if (!legacyMode) {
-          keyType = instantiateToBounds(keyType, coreTypes.objectClass);
-          valueType = instantiateToBounds(valueType, coreTypes.objectClass);
-        }
+        keyType = instantiateToBounds(keyType, coreTypes.objectClass);
+        valueType = instantiateToBounds(valueType, coreTypes.objectClass);
       }
     } else {
       DartType implicitTypeArgument = this.implicitTypeArgument;
@@ -2878,7 +2845,10 @@
     FormalParameters formals = pop();
     UnresolvedType returnType = pop();
     List<TypeVariableBuilder> typeVariables = pop();
-    UnresolvedType type = formals.toFunctionType(returnType, typeVariables);
+    UnresolvedType type = formals.toFunctionType(
+        returnType,
+        libraryBuilder.computeNullabilityFromToken(questionMark != null),
+        typeVariables);
     exitLocalScope();
     push(type);
   }
@@ -3099,7 +3069,10 @@
     if (!libraryBuilder.loader.target.enableNonNullable) {
       reportErrorIfNullableType(question);
     }
-    UnresolvedType type = formals.toFunctionType(returnType, typeVariables);
+    UnresolvedType type = formals.toFunctionType(
+        returnType,
+        libraryBuilder.computeNullabilityFromToken(question != null),
+        typeVariables);
     exitLocalScope();
     push(type);
     functionNestingLevel--;
@@ -3210,7 +3183,7 @@
         if (parameterCount > 1) {
           stackTrace = catchParameters.parameters[1];
           stackTrace.build(libraryBuilder, functionNestingLevel).type =
-              coreTypes.stackTraceClass.rawType;
+              coreTypes.stackTraceRawType(libraryBuilder.nonNullable);
         }
       }
       if (parameterCount > 2) {
@@ -3232,7 +3205,7 @@
         catchKeyword,
         exception?.target,
         stackTrace?.target,
-        coreTypes.stackTraceClass.rawType,
+        coreTypes.stackTraceRawType(libraryBuilder.nonNullable),
         body));
     if (compileTimeErrors == null) {
       push(NullValue.Block);
@@ -3463,33 +3436,33 @@
       int charLength: noLength}) {
     // The argument checks for the initial target of redirecting factories
     // invocations are skipped in Dart 1.
-    if (!legacyMode || !isRedirectingFactory(target, helper: this)) {
-      List<TypeParameter> typeParameters = target.function.typeParameters;
-      if (target is Constructor) {
-        assert(!target.enclosingClass.isAbstract);
-        typeParameters = target.enclosingClass.typeParameters;
-      }
-      LocatedMessage argMessage = checkArgumentsForFunction(
-          target.function, arguments, charOffset, typeParameters);
-      if (argMessage != null) {
-        return wrapSyntheticExpression(
-            throwNoSuchMethodError(
-                forest.createNullLiteral(null)..fileOffset = charOffset,
-                target.name.name,
-                arguments,
-                charOffset,
-                candidate: target,
-                message: argMessage),
-            charOffset);
-      }
+    List<TypeParameter> typeParameters = target.function.typeParameters;
+    if (target is Constructor) {
+      assert(!target.enclosingClass.isAbstract);
+      typeParameters = target.enclosingClass.typeParameters;
+    }
+    LocatedMessage argMessage = checkArgumentsForFunction(
+        target.function, arguments, charOffset, typeParameters);
+    if (argMessage != null) {
+      return wrapSyntheticExpression(
+          throwNoSuchMethodError(
+              forest.createNullLiteral(null)..fileOffset = charOffset,
+              target.name.name,
+              arguments,
+              charOffset,
+              candidate: target,
+              message: argMessage),
+          charOffset);
     }
 
-    bool isConst = constness == Constness.explicitConst;
+    bool isConst = constness == Constness.explicitConst ||
+        constantContext != ConstantContext.none;
     if (target is Constructor) {
-      isConst =
-          isConst || constantContext != ConstantContext.none && target.isConst;
-      if ((isConst || constantContext == ConstantContext.inferred) &&
-          !target.isConst) {
+      if (constantContext == ConstantContext.required &&
+          constness == Constness.implicit) {
+        addProblem(fasta.messageMissingExplicitConst, charOffset, charLength);
+      }
+      if (isConst && !target.isConst) {
         return wrapInvalidConstructorInvocation(
             desugarSyntheticExpression(buildProblem(
                 fasta.messageNonConstConstructor, charOffset, charLength)),
@@ -3506,10 +3479,11 @@
     } else {
       Procedure procedure = target;
       if (procedure.isFactory) {
-        isConst = isConst ||
-            constantContext != ConstantContext.none && procedure.isConst;
-        if ((isConst || constantContext == ConstantContext.inferred) &&
-            !procedure.isConst) {
+        if (constantContext == ConstantContext.required &&
+            constness == Constness.implicit) {
+          addProblem(fasta.messageMissingExplicitConst, charOffset, charLength);
+        }
+        if (isConst && !procedure.isConst) {
           return wrapInvalidConstructorInvocation(
               desugarSyntheticExpression(buildProblem(
                   fasta.messageNonConstFactory, charOffset, charLength)),
@@ -3525,8 +3499,9 @@
             node, typeEnvironment, uri);
         return node;
       } else {
+        assert(constness == Constness.implicit);
         StaticInvocation node =
-            new StaticInvocation(target, arguments, isConst: isConst)
+            new StaticInvocation(target, arguments, isConst: false)
               ..fileOffset = charOffset;
         libraryBuilder.checkBoundsInStaticInvocation(
             node, typeEnvironment, uri);
@@ -3594,12 +3569,7 @@
     if (typeParameters.length != types.length) {
       if (types.length == 0) {
         // Expected `typeParameters.length` type arguments, but none given, so
-        // we fill in dynamic in legacy mode, and use type inference otherwise.
-        if (legacyMode) {
-          for (int i = 0; i < typeParameters.length; i++) {
-            types.add(const DynamicType());
-          }
-        }
+        // we use type inference.
       } else {
         // A wrong (non-zero) amount of type arguments given. That's an error.
         // TODO(jensj): Position should be on type arguments instead.
@@ -3813,31 +3783,10 @@
           (target is Procedure && target.kind == ProcedureKind.Factory)) {
         Expression invocation;
 
-        if (legacyMode && isRedirectingFactory(target, helper: this)) {
-          // In legacy mode the checks that are done in [buildStaticInvocation]
-          // on the initial target of a redirecting factory invocation should
-          // be skipped. So we build the invocation nodes directly here without
-          // doing any checks.
-          if (target.function.typeParameters != null &&
-              target.function.typeParameters.length !=
-                  forest.argumentsTypeArguments(arguments).length) {
-            arguments = forest.createArguments(
-                noLocation, forest.argumentsPositional(arguments),
-                named: forest.argumentsNamed(arguments),
-                types: new List<DartType>.filled(
-                    target.function.typeParameters.length, const DynamicType(),
-                    growable: true));
-          }
-          invocation = new FactoryConstructorInvocationJudgment(
-              target, arguments,
-              isConst: constness == Constness.explicitConst)
-            ..fileOffset = nameToken.charOffset;
-        } else {
-          invocation = buildStaticInvocation(target, arguments,
-              constness: constness,
-              charOffset: nameToken.charOffset,
-              charLength: nameToken.length);
-        }
+        invocation = buildStaticInvocation(target, arguments,
+            constness: constness,
+            charOffset: nameToken.charOffset,
+            charLength: nameToken.length);
 
         if (invocation is StaticInvocation &&
             isRedirectingFactory(target, helper: this)) {
@@ -4041,7 +3990,7 @@
     debugEvent("FunctionName");
     Identifier name = pop();
     Token nameToken = deprecated_extractToken(name);
-    VariableDeclaration variable = new VariableDeclarationJudgment(
+    VariableDeclaration variable = new VariableDeclarationImpl(
         name.name, functionNestingLevel,
         forSyntheticToken: nameToken.isSynthetic,
         isFinal: true,
@@ -4053,7 +4002,7 @@
     if (existing != null) {
       reportDuplicatedDeclaration(existing, name.name, name.charOffset);
     }
-    push(new FunctionDeclarationJudgment(
+    push(new FunctionDeclarationImpl(
         variable,
         // The function node is created later.
         null)
@@ -4117,8 +4066,14 @@
     if (!isFunctionExpression) {
       annotations = pop(); // Metadata.
     }
-    FunctionNode function = formals.buildFunctionNode(libraryBuilder,
-        returnType, typeParameters, asyncModifier, body, token.charOffset);
+    FunctionNode function = formals.buildFunctionNode(
+        libraryBuilder,
+        returnType,
+        typeParameters,
+        asyncModifier,
+        body,
+        const NullabilityBuilder.pendingImplementation(),
+        token.charOffset);
 
     if (declaration is FunctionDeclaration) {
       VariableDeclaration variable = declaration.variable;
@@ -4127,7 +4082,7 @@
           variable.addAnnotation(annotation);
         }
       }
-      FunctionDeclarationJudgment.setHasImplicitReturnType(
+      FunctionDeclarationImpl.setHasImplicitReturnType(
           declaration, hasImplicitReturnType);
 
       variable.type = function.functionType;
@@ -4199,28 +4154,16 @@
     FormalParameters formals = pop();
     exitFunction();
     List<TypeVariableBuilder> typeParameters = pop();
-    FunctionNode function = formals.buildFunctionNode(libraryBuilder, null,
-        typeParameters, asyncModifier, body, token.charOffset)
+    FunctionNode function = formals.buildFunctionNode(
+        libraryBuilder,
+        null,
+        typeParameters,
+        asyncModifier,
+        body,
+        const NullabilityBuilder.pendingImplementation(),
+        token.charOffset)
       ..fileOffset = beginToken.charOffset;
 
-    if (libraryBuilder.legacyMode && asyncModifier != AsyncMarker.Sync) {
-      DartType returnType;
-      switch (asyncModifier) {
-        case AsyncMarker.Async:
-          returnType = coreTypes.futureClass.rawType;
-          break;
-        case AsyncMarker.AsyncStar:
-          returnType = coreTypes.streamClass.rawType;
-          break;
-        case AsyncMarker.SyncStar:
-          returnType = coreTypes.iterableClass.rawType;
-          break;
-        default:
-          returnType = const DynamicType();
-          break;
-      }
-      function.returnType = returnType;
-    }
     if (constantContext != ConstantContext.none) {
       push(buildProblem(fasta.messageNotAConstantExpression, formals.charOffset,
           formals.length));
@@ -4349,7 +4292,7 @@
           typePromoter?.getFactForAccess(variable, functionNestingLevel);
       TypePromotionScope scope = typePromoter?.currentScope;
       Expression syntheticAssignment = lvalue.buildAssignment(
-          new VariableGetJudgment(variable, fact, scope)
+          new VariableGetImpl(variable, fact, scope)
             ..fileOffset = inKeyword.offset,
           voidContext: true);
       if (syntheticAssignment is shadow.SyntheticExpressionJudgment) {
@@ -4482,10 +4425,8 @@
     if (inCatchBlock) {
       push(forest.createRethrowStatement(rethrowToken, endToken));
     } else {
-      push(new ExpressionStatementJudgment(buildProblem(
-          fasta.messageRethrowNotCatch,
-          offsetForToken(rethrowToken),
-          lengthForToken(rethrowToken)))
+      push(new ExpressionStatement(buildProblem(fasta.messageRethrowNotCatch,
+          offsetForToken(rethrowToken), lengthForToken(rethrowToken)))
         ..fileOffset = offsetForToken(rethrowToken));
     }
   }
@@ -4638,7 +4579,7 @@
     for (Expression expression in expressions) {
       expressionOffsets.add(forest.readOffset(expression));
     }
-    push(new SwitchCaseJudgment(expressions, expressionOffsets, block,
+    push(new SwitchCase(expressions, expressionOffsets, block,
         isDefault: defaultKeyword != null)
       ..fileOffset = firstToken.charOffset);
     push(labels ?? NullValue.Labels);
@@ -4653,7 +4594,7 @@
     exitSwitchScope();
     exitLocalScope();
     Expression expression = popForValue();
-    Statement result = new SwitchStatementJudgment(expression, cases)
+    Statement result = new SwitchStatement(expression, cases)
       ..fileOffset = switchKeyword.charOffset;
     if (target.hasUsers) {
       result = forest.createLabeledStatement(result);
@@ -4799,7 +4740,7 @@
       }
       if (target.isGotoTarget &&
           target.functionNestingLevel == functionNestingLevel) {
-        ContinueSwitchStatement statement = new ContinueSwitchJudgment(null)
+        ContinueSwitchStatement statement = new ContinueSwitchStatement(null)
           ..fileOffset = continueKeyword.charOffset;
         target.addGoto(statement);
         push(statement);
@@ -4869,32 +4810,19 @@
     // Peek to leave type parameters on top of stack.
     List<TypeVariableBuilder> typeVariables = peek();
 
-    if (!legacyMode) {
-      List<TypeBuilder> calculatedBounds = calculateBounds(
-          typeVariables,
-          libraryBuilder.loader.target.dynamicType,
-          libraryBuilder.loader.target.bottomType,
-          libraryBuilder.loader.target.objectClassBuilder);
-      for (int i = 0; i < typeVariables.length; ++i) {
-        typeVariables[i].defaultType = calculatedBounds[i];
-        typeVariables[i].defaultType.resolveIn(
-            scope,
-            typeVariables[i].charOffset,
-            typeVariables[i].fileUri,
-            libraryBuilder);
-        typeVariables[i].finish(
-            libraryBuilder,
-            libraryBuilder.loader.target.objectClassBuilder,
-            libraryBuilder.loader.target.dynamicType);
-      }
-    } else {
-      for (int i = 0; i < typeVariables.length; ++i) {
-        typeVariables[i].defaultType = libraryBuilder.loader.target.dynamicType;
-        typeVariables[i].finish(
-            libraryBuilder,
-            libraryBuilder.loader.target.objectClassBuilder,
-            libraryBuilder.loader.target.dynamicType);
-      }
+    List<TypeBuilder> calculatedBounds = calculateBounds(
+        typeVariables,
+        libraryBuilder.loader.target.dynamicType,
+        libraryBuilder.loader.target.bottomType,
+        libraryBuilder.loader.target.objectClassBuilder);
+    for (int i = 0; i < typeVariables.length; ++i) {
+      typeVariables[i].defaultType = calculatedBounds[i];
+      typeVariables[i].defaultType.resolveIn(scope, typeVariables[i].charOffset,
+          typeVariables[i].fileUri, libraryBuilder);
+      typeVariables[i].finish(
+          libraryBuilder,
+          libraryBuilder.loader.target.objectClassBuilder,
+          libraryBuilder.loader.target.dynamicType);
     }
   }
 
@@ -4927,15 +4855,20 @@
 
   @override
   Expression buildProblem(Message message, int charOffset, int length,
-      {List<LocatedMessage> context, bool suppressMessage: false}) {
+      {List<LocatedMessage> context,
+      bool suppressMessage: false,
+      bool wrapInSyntheticExpression: true}) {
     if (!suppressMessage) {
       addProblem(message, charOffset, length,
           wasHandled: true, context: context);
     }
     String text = libraryBuilder.loader.target.context
         .format(message.withLocation(uri, charOffset, length), Severity.error);
-    return wrapSyntheticExpression(
-        new InvalidExpression(text)..fileOffset = charOffset, charOffset);
+    InvalidExpression expression = new InvalidExpression(text)
+      ..fileOffset = charOffset;
+    return wrapInSyntheticExpression
+        ? wrapSyntheticExpression(expression, charOffset)
+        : expression;
   }
 
   @override
@@ -4943,8 +4876,7 @@
       {List<LocatedMessage> context}) {
     int charOffset = forest.readOffset(expression);
     Severity severity = message.code.severity;
-    if (severity == Severity.error ||
-        severity == Severity.errorLegacyWarning && !legacyMode) {
+    if (severity == Severity.error || severity == Severity.errorLegacyWarning) {
       return wrapInLocatedProblem(
           expression, message.withLocation(uri, charOffset, length),
           context: context);
@@ -4993,6 +4925,7 @@
               forest.createIntLiteral(location?.line ?? 0, null)
                 ..fileOffset = charOffset,
             ]),
+            constness: Constness.explicitNew,
             charOffset: charOffset))
       ..fileOffset = charOffset;
   }
@@ -5009,6 +4942,7 @@
         forest.createArguments(charOffset, <Expression>[
           forest.createStringLiteral(className, null)..fileOffset = charOffset
         ]),
+        constness: Constness.explicitNew,
         charOffset: charOffset);
     if (invocation is shadow.SyntheticExpressionJudgment) {
       invocation = desugarSyntheticExpression(invocation);
@@ -5019,8 +4953,7 @@
   Statement buildProblemStatement(Message message, int charOffset,
       {List<LocatedMessage> context, int length, bool suppressMessage: false}) {
     length ??= noLength;
-    return new ExpressionStatementJudgment(buildProblem(
-        message, charOffset, length,
+    return new ExpressionStatement(buildProblem(message, charOffset, length,
         context: context, suppressMessage: suppressMessage));
   }
 
@@ -5040,7 +4973,7 @@
   }
 
   Initializer buildInvalidSuperInitializer(
-      Constructor target, ArgumentsJudgment arguments, Expression expression,
+      Constructor target, ArgumentsImpl arguments, Expression expression,
       [int charOffset = -1]) {
     needsImplicitSuperInitializer = false;
     return new InvalidSuperInitializerJudgment(
@@ -5113,6 +5046,7 @@
               forest.createStringLiteral(name, null)
                 ..fileOffset = assignmentOffset
             ]),
+            constness: Constness.explicitNew,
             charOffset: assignmentOffset);
         if (invocation is shadow.SyntheticExpressionJudgment) {
           invocation = desugarSyntheticExpression(invocation);
@@ -5125,8 +5059,7 @@
                   ..fileOffset = assignmentOffset))
           ..fileOffset = assignmentOffset;
       } else {
-        if (!legacyMode &&
-            formalType != null &&
+        if (formalType != null &&
             !typeEnvironment.isSubtypeOf(formalType, builder.field.type)) {
           libraryBuilder.addProblem(
               fasta.templateInitializingFormalTypeMismatch
@@ -5139,7 +5072,7 @@
                     .withLocation(builder.fileUri, builder.charOffset, noLength)
               ]);
         }
-        return new ShadowFieldInitializer(builder.field, expression)
+        return new FieldInitializer(builder.field, expression)
           ..fileOffset = assignmentOffset
           ..isSynthetic = isSynthetic;
       }
@@ -5168,7 +5101,7 @@
           charOffset);
     }
     needsImplicitSuperInitializer = false;
-    return new SuperInitializerJudgment(constructor, arguments)
+    return new SuperInitializer(constructor, arguments)
       ..fileOffset = charOffset
       ..isSynthetic = isSynthetic;
   }
@@ -5185,7 +5118,7 @@
       // TODO(askesc): Produce invalid initializer.
     }
     needsImplicitSuperInitializer = false;
-    return new RedirectingInitializerJudgment(constructor, arguments)
+    return new RedirectingInitializer(constructor, arguments)
       ..fileOffset = charOffset;
   }
 
@@ -5262,7 +5195,8 @@
     for (Expression argument in expressions.reversed) {
       expression = new Let(
           new VariableDeclaration.forValue(argument,
-              isFinal: true, type: coreTypes.objectClass.rawType),
+              isFinal: true,
+              type: coreTypes.objectRawType(libraryBuilder.nullable)),
           expression);
     }
     return expression;
@@ -5302,14 +5236,12 @@
               offset,
               name.name.length);
         }
-        return new SuperMethodInvocationJudgment(name, arguments,
-            interfaceTarget: target)
+        return new SuperMethodInvocation(name, arguments, target)
           ..fileOffset = offset;
       }
 
-      receiver = new SuperPropertyGetJudgment(name, interfaceTarget: target)
-        ..fileOffset = offset;
-      MethodInvocation node = new MethodInvocationJudgment(
+      receiver = new SuperPropertyGet(name, target)..fileOffset = offset;
+      MethodInvocation node = new MethodInvocationImpl(
           receiver, callName, arguments,
           isImplicitCall: true)
         ..fileOffset = forest.readOffset(arguments);
@@ -5317,24 +5249,18 @@
     }
 
     if (isNullAware) {
-      VariableDeclaration variable = new VariableDeclaration.forValue(receiver);
-      return new NullAwareMethodInvocationJudgment(
+      VariableDeclaration variable = forest.createVariableDeclarationForValue(
+          receiver.fileOffset, receiver);
+      return new NullAwareMethodInvocation(
           variable,
-          forest.createConditionalExpression(
-              buildIsNull(new VariableGet(variable), offset, this),
-              null,
-              forest.createNullLiteral(null)..fileOffset = offset,
-              null,
-              new MethodInvocation(
-                  new VariableGet(variable), name, arguments, interfaceTarget)
-                ..fileOffset = offset)
-            ..fileOffset = offset)
-        ..fileOffset = offset;
+          forest.createMethodInvocation(offset,
+              createVariableGet(variable, receiver.fileOffset), name, arguments,
+              isImplicitCall: isImplicitCall, interfaceTarget: interfaceTarget))
+        ..fileOffset = receiver.fileOffset;
     } else {
-      MethodInvocation node = new MethodInvocationJudgment(
-          receiver, name, arguments,
-          isImplicitCall: isImplicitCall, interfaceTarget: interfaceTarget)
-        ..fileOffset = offset;
+      MethodInvocation node = forest.createMethodInvocation(
+          offset, receiver, name, arguments,
+          isImplicitCall: isImplicitCall, interfaceTarget: interfaceTarget);
       return node;
     }
   }
@@ -5394,7 +5320,7 @@
     VariableDeclaration check = new VariableDeclaration.forValue(
         forest.checkLibraryIsLoaded(prefix.dependency))
       ..fileOffset = charOffset;
-    return new DeferredCheckJudgment(check, expression);
+    return new DeferredCheck(check, expression);
   }
 
   /// TODO(ahe): This method is temporarily implemented. Once type promotion is
@@ -5446,14 +5372,12 @@
 
   @override
   Expression wrapSyntheticExpression(Expression desugared, int charOffset) {
-    if (legacyMode) return desugared;
     return shadow.SyntheticWrapper.wrapSyntheticExpression(desugared)
       ..fileOffset = charOffset;
   }
 
   @override
   Expression desugarSyntheticExpression(Expression node) {
-    if (legacyMode) return node;
     shadow.SyntheticExpressionJudgment shadowNode = node;
     return shadowNode.desugared;
   }
@@ -5461,7 +5385,6 @@
   @override
   Expression wrapInvalidConstructorInvocation(Expression desugared,
       Member constructor, Arguments arguments, int charOffset) {
-    if (legacyMode) return desugared;
     return shadow.SyntheticWrapper.wrapInvalidConstructorInvocation(
         desugared, constructor, arguments)
       ..fileOffset = charOffset;
@@ -5470,7 +5393,6 @@
   @override
   Expression wrapInvalidWrite(
       Expression desugared, Expression expression, int charOffset) {
-    if (legacyMode) return desugared;
     return shadow.SyntheticWrapper.wrapInvalidWrite(desugared, expression)
       ..fileOffset = charOffset;
   }
@@ -5478,7 +5400,6 @@
   @override
   Expression wrapUnresolvedTargetInvocation(
       Expression desugared, Arguments arguments, int charOffset) {
-    if (legacyMode) return desugared;
     return shadow.SyntheticWrapper.wrapUnresolvedTargetInvocation(
         desugared, arguments)
       ..fileOffset = charOffset;
@@ -5487,7 +5408,6 @@
   @override
   Expression wrapUnresolvedVariableAssignment(
       Expression desugared, bool isCompound, Expression rhs, int charOffset) {
-    if (legacyMode) return desugared;
     return shadow.SyntheticWrapper.wrapUnresolvedVariableAssignment(
         desugared, isCompound, rhs)
       ..fileOffset = charOffset;
@@ -5660,9 +5580,12 @@
       List<TypeVariableBuilder> typeParameters,
       AsyncMarker asyncModifier,
       Statement body,
+      NullabilityBuilder nullabilityBuilder,
       int fileEndOffset) {
     FunctionType type =
-        toFunctionType(returnType, typeParameters).builder.build(library);
+        toFunctionType(returnType, nullabilityBuilder, typeParameters)
+            .builder
+            .build(library);
     List<VariableDeclaration> positionalParameters = <VariableDeclaration>[];
     List<VariableDeclaration> namedParameters = <VariableDeclaration>[];
     if (parameters != null) {
@@ -5677,7 +5600,7 @@
         return a.name.compareTo(b.name);
       });
     }
-    return new FunctionNodeJudgment(body,
+    return new FunctionNode(body,
         typeParameters: type.typeParameters,
         positionalParameters: positionalParameters,
         namedParameters: namedParameters,
@@ -5688,11 +5611,12 @@
       ..fileEndOffset = fileEndOffset;
   }
 
-  UnresolvedType toFunctionType(UnresolvedType returnType,
+  UnresolvedType toFunctionType(
+      UnresolvedType returnType, NullabilityBuilder nullabilityBuilder,
       [List<TypeVariableBuilder> typeParameters]) {
     return new UnresolvedType(
-        new FunctionTypeBuilder(
-            returnType?.builder, typeParameters, parameters),
+        new FunctionTypeBuilder(returnType?.builder, typeParameters, parameters,
+            nullabilityBuilder),
         charOffset,
         uri);
   }
@@ -5738,7 +5662,7 @@
     statement.parent = body;
     return body;
   } else {
-    return new BlockJudgment(<Statement>[statement, body])
+    return new Block(<Statement>[statement, body])
       ..fileOffset = statement.fileOffset;
   }
 }
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 075dc56..39d84cb 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
@@ -215,7 +215,7 @@
 
   final List<DelayedMember> delayedMemberChecks = <DelayedMember>[];
 
-  // TODO(ahe): Remove this.
+  // TODO(dmitryas): Consider removing this.
   final CoreTypes coreTypes;
 
   Types types;
@@ -275,20 +275,20 @@
     if (kernelClass == superclass) return type;
     if (kernelClass == nullClass) {
       if (superclass.typeParameters.isEmpty) {
-        return superclass.rawType;
+        return coreTypes.legacyRawType(superclass);
       } else {
         // This is a safe fall-back for dealing with `Null`. It will likely be
         // faster to check for `Null` before calling this method.
         return new InterfaceType(
             superclass,
             new List<DartType>.filled(
-                superclass.typeParameters.length, nullClass.rawType));
+                superclass.typeParameters.length, coreTypes.nullType));
       }
     }
     NamedTypeBuilder supertype = asSupertypeOf(kernelClass, superclass);
     if (supertype == null) return null;
     if (supertype.arguments == null && superclass.typeParameters.isEmpty) {
-      return superclass.rawType;
+      return coreTypes.legacyRawType(superclass);
     }
     return Substitution.fromInterfaceType(type)
         .substituteType(supertype.build(null));
@@ -317,7 +317,7 @@
       }
     }
 
-    if (common.length == 1) return objectClass.rawType;
+    if (common.length == 1) return coreTypes.objectLegacyRawType;
     common.sort(ClassHierarchyNode.compareMaxInheritancePath);
 
     for (int i = 0; i < common.length - 1; i++) {
@@ -330,7 +330,7 @@
         } while (node.maxInheritancePath == common[i + 1].maxInheritancePath);
       }
     }
-    return objectClass.rawType;
+    return coreTypes.objectLegacyRawType;
   }
 
   Member getInterfaceMemberKernel(Class cls, Name name, bool isSetter) {
@@ -1961,13 +1961,14 @@
   Class get nullClass => hierarchy.nullClass;
 
   @override
-  InterfaceType get nullType => nullClass.rawType;
+  InterfaceType get nullType => hierarchy.coreTypes.nullType;
 
   @override
-  InterfaceType get objectType => objectClass.rawType;
+  InterfaceType get objectType => hierarchy.coreTypes.objectLegacyRawType;
 
   @override
-  InterfaceType get rawFunctionType => functionClass.rawType;
+  InterfaceType get rawFunctionType =>
+      hierarchy.coreTypes.functionLegacyRawType;
 
   @override
   void addLowerBound(TypeConstraint constraint, DartType lower) {
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 73b8e87..fa0afb1 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -60,11 +60,12 @@
         templateConstEvalInvalidStringInterpolationOperand,
         templateConstEvalInvalidSymbolName,
         templateConstEvalKeyImplementsEqual,
-        templateConstEvalNegativeShift,
         templateConstEvalNonConstantLiteral,
         templateConstEvalNonConstantVariableGet,
         templateConstEvalZeroDivisor;
 
+import 'constant_int_folder.dart';
+
 part 'constant_collection_builders.dart';
 
 Component transformComponent(Component component, ConstantsBackend backend,
@@ -116,22 +117,6 @@
   }
 }
 
-class JavaScriptIntConstant extends DoubleConstant {
-  final BigInt bigIntValue;
-  JavaScriptIntConstant(int value) : this.fromBigInt(new BigInt.from(value));
-  JavaScriptIntConstant.fromDouble(double value)
-      : bigIntValue = new BigInt.from(value),
-        super(value);
-  JavaScriptIntConstant.fromBigInt(this.bigIntValue)
-      : super(bigIntValue.toDouble());
-  JavaScriptIntConstant.fromUInt64(int value)
-      : this.fromBigInt(new BigInt.from(value).toUnsigned(64));
-
-  DartType getType(TypeEnvironment types) => types.intType;
-
-  String toString() => '$bigIntValue';
-}
-
 class ConstantsTransformer extends Transformer {
   final ConstantsBackend backend;
   final ConstantEvaluator constantEvaluator;
@@ -499,6 +484,7 @@
 class ConstantEvaluator extends RecursiveVisitor<Constant> {
   final ConstantsBackend backend;
   final NumberSemantics numberSemantics;
+  ConstantIntFolder intFolder;
   Map<String, String> environmentDefines;
   final bool errorOnUnevaluatedConstant;
   final CoreTypes coreTypes;
@@ -552,6 +538,7 @@
           "No 'environmentDefines' passed to the constant evaluator but the "
           "ConstantsBackend does not support unevaluated constants.");
     }
+    intFolder = new ConstantIntFolder.forSemantics(this, numberSemantics);
     primitiveEqualCache = <Class, bool>{
       coreTypes.boolClass: true,
       coreTypes.doubleClass: false,
@@ -795,14 +782,12 @@
   Constant visitIntLiteral(IntLiteral node) {
     // The frontend ensures that integer literals are valid according to the
     // target representation.
-    return targetingJavaScript
-        ? canonicalize(new JavaScriptIntConstant.fromUInt64(node.value))
-        : canonicalize(new IntConstant(node.value));
+    return canonicalize(intFolder.makeIntConstant(node.value, unsigned: true));
   }
 
   @override
   Constant visitDoubleLiteral(DoubleLiteral node) {
-    return canonicalize(makeDoubleConstant(node.value));
+    return canonicalize(new DoubleConstant(node.value));
   }
 
   @override
@@ -824,14 +809,6 @@
       result = runInsideContext(constant.expression, () {
         return _evaluateSubexpression(constant.expression);
       });
-    } else if (targetingJavaScript) {
-      if (constant is DoubleConstant) {
-        double value = constant.value;
-        // TODO(askesc, fishythefish): Handle infinite integers.
-        if (value.isFinite && value.truncateToDouble() == value) {
-          result = new JavaScriptIntConstant.fromDouble(value);
-        }
-      }
     }
     // If there were already constants in the AST then we make sure we
     // re-canonicalize them.  After running the transformer we will therefore
@@ -1293,25 +1270,16 @@
     if (arguments.length == 1 && op == '==') {
       final Constant right = arguments[0];
 
-      // [DoubleConstant] uses [identical] to determine equality, so we need two
-      // special cases:
-      // Two NaNs are always unequal even if [identical] returns `true`.
-      if (isNaN(receiver) || isNaN(right)) {
-        return falseConstant;
-      }
-
-      // Two zero values are always equal regardless of sign.
-      if (isZero(receiver)) {
-        return makeBoolConstant(isZero(right));
-      }
-
       if (receiver is NullConstant ||
           receiver is BoolConstant ||
           receiver is IntConstant ||
           receiver is DoubleConstant ||
           receiver is StringConstant ||
           right is NullConstant) {
-        return makeBoolConstant(receiver == right);
+        // [DoubleConstant] uses [identical] to determine equality, so we need
+        // to take the special cases into account.
+        return doubleSpecialCases(receiver, right) ??
+            makeBoolConstant(receiver == right);
       } else {
         return report(
             node,
@@ -1339,112 +1307,14 @@
                     other.getType(typeEnvironment)));
         }
       }
-    } else if (receiver is IntConstant || receiver is JavaScriptIntConstant) {
+    } else if (intFolder.isInt(receiver)) {
       if (arguments.length == 0) {
-        switch (op) {
-          case 'unary-':
-            if (targetingJavaScript) {
-              BigInt value = (receiver as JavaScriptIntConstant).bigIntValue;
-              if (value == BigInt.zero) {
-                return canonicalize(new DoubleConstant(-0.0));
-              }
-              return canonicalize(new JavaScriptIntConstant.fromBigInt(-value));
-            }
-            int value = (receiver as IntConstant).value;
-            return canonicalize(new IntConstant(-value));
-          case '~':
-            if (targetingJavaScript) {
-              BigInt value = (receiver as JavaScriptIntConstant).bigIntValue;
-              return canonicalize(new JavaScriptIntConstant.fromBigInt(
-                  (~value).toUnsigned(32)));
-            }
-            int value = (receiver as IntConstant).value;
-            return canonicalize(new IntConstant(~value));
-        }
+        return canonicalize(intFolder.foldUnaryOperator(node, op, receiver));
       } else if (arguments.length == 1) {
         final Constant other = arguments[0];
-        if (other is IntConstant || other is JavaScriptIntConstant) {
-          if ((op == '<<' || op == '>>' || op == '>>>')) {
-            Object receiverValue = receiver is IntConstant
-                ? receiver.value
-                : (receiver as JavaScriptIntConstant).bigIntValue;
-            int otherValue = other is IntConstant
-                ? other.value
-                : (other as JavaScriptIntConstant).bigIntValue.toInt();
-            if (otherValue < 0) {
-              return report(
-                  node.arguments.positional.first,
-                  // TODO(askesc): Change argument types in template to
-                  // constants.
-                  templateConstEvalNegativeShift.withArguments(
-                      op, '${receiverValue}', '${otherValue}'));
-            }
-          }
-
-          if ((op == '%' || op == '~/')) {
-            Object receiverValue = receiver is IntConstant
-                ? receiver.value
-                : (receiver as JavaScriptIntConstant).bigIntValue;
-            int otherValue = other is IntConstant
-                ? other.value
-                : (other as JavaScriptIntConstant).bigIntValue.toInt();
-            if (otherValue == 0) {
-              return report(
-                  node.arguments.positional.first,
-                  // TODO(askesc): Change argument type in template to constant.
-                  templateConstEvalZeroDivisor.withArguments(
-                      op, '${receiverValue}'));
-            }
-          }
-
-          switch (op) {
-            case '|':
-            case '&':
-            case '^':
-              int receiverValue = receiver is IntConstant
-                  ? receiver.value
-                  : (receiver as JavaScriptIntConstant)
-                      .bigIntValue
-                      .toUnsigned(32)
-                      .toInt();
-              int otherValue = other is IntConstant
-                  ? other.value
-                  : (other as JavaScriptIntConstant)
-                      .bigIntValue
-                      .toUnsigned(32)
-                      .toInt();
-              return evaluateBinaryBitOperation(
-                  op, receiverValue, otherValue, node);
-            case '<<':
-            case '>>':
-            case '>>>':
-              bool negative = false;
-              int receiverValue;
-              if (receiver is IntConstant) {
-                receiverValue = receiver.value;
-              } else {
-                BigInt bigIntValue =
-                    (receiver as JavaScriptIntConstant).bigIntValue;
-                receiverValue = bigIntValue.toUnsigned(32).toInt();
-                negative = bigIntValue.isNegative;
-              }
-              int otherValue = other is IntConstant
-                  ? other.value
-                  : (other as JavaScriptIntConstant).bigIntValue.toInt();
-
-              return evaluateBinaryShiftOperation(
-                  op, receiverValue, otherValue, node,
-                  negativeReceiver: negative);
-            default:
-              num receiverValue = receiver is IntConstant
-                  ? receiver.value
-                  : (receiver as DoubleConstant).value;
-              num otherValue = other is IntConstant
-                  ? other.value
-                  : (other as DoubleConstant).value;
-              return evaluateBinaryNumericOperation(
-                  op, receiverValue, otherValue, node);
-          }
+        if (intFolder.isInt(other)) {
+          return canonicalize(
+              intFolder.foldBinaryOperator(node, op, receiver, other));
         } else if (other is DoubleConstant) {
           if ((op == '|' || op == '&' || op == '^') ||
               (op == '<<' || op == '>>' || op == '>>>')) {
@@ -1456,11 +1326,9 @@
                     typeEnvironment.intType,
                     other.getType(typeEnvironment)));
           }
-          num receiverValue = receiver is IntConstant
-              ? receiver.value
-              : (receiver as DoubleConstant).value;
-          return evaluateBinaryNumericOperation(
-              op, receiverValue, other.value, node);
+          num receiverValue = (receiver as PrimitiveConstant<num>).value;
+          return canonicalize(evaluateBinaryNumericOperation(
+              op, receiverValue, other.value, node));
         }
         return report(
             node,
@@ -1484,17 +1352,15 @@
       if (arguments.length == 0) {
         switch (op) {
           case 'unary-':
-            return canonicalize(makeDoubleConstant(-receiver.value));
+            return canonicalize(new DoubleConstant(-receiver.value));
         }
       } else if (arguments.length == 1) {
         final Constant other = arguments[0];
 
         if (other is IntConstant || other is DoubleConstant) {
-          final num value = (other is IntConstant)
-              ? other.value
-              : (other as DoubleConstant).value;
-          return evaluateBinaryNumericOperation(
-              op, receiver.value, value, node);
+          final num value = (other as PrimitiveConstant<num>).value;
+          return canonicalize(
+              evaluateBinaryNumericOperation(op, receiver.value, value, node));
         }
         return report(
             node,
@@ -1636,10 +1502,7 @@
 
     final Constant receiver = _evaluateSubexpression(node.receiver);
     if (receiver is StringConstant && node.name.name == 'length') {
-      if (targetingJavaScript) {
-        return canonicalize(new JavaScriptIntConstant(receiver.value.length));
-      }
-      return canonicalize(new IntConstant(receiver.value.length));
+      return canonicalize(intFolder.makeIntConstant(receiver.value.length));
     } else if (shouldBeUnevaluated) {
       return unevaluated(node,
           new PropertyGet(extract(receiver), node.name, node.interfaceTarget));
@@ -1717,7 +1580,12 @@
     for (int i = 0; i < node.expressions.length; i++) {
       Constant constant = _evaluateSubexpression(node.expressions[i]);
       if (constant is PrimitiveConstant<Object>) {
-        String value = constant.toString();
+        String value;
+        if (constant is DoubleConstant && intFolder.isInt(constant)) {
+          value = new BigInt.from(constant.value).toString();
+        } else {
+          value = constant.toString();
+        }
         Object last = concatenated.last;
         if (last is StringBuffer) {
           last.write(value);
@@ -1793,16 +1661,17 @@
               return boolConstant;
             } else if (target.enclosingClass == coreTypes.intClass) {
               int intValue = value != null ? int.tryParse(value) : null;
-              intValue ??= defaultValue is IntConstant
-                  ? defaultValue.value
-                  : defaultValue is JavaScriptIntConstant
-                      ? defaultValue.bigIntValue.toInt()
-                      : null;
-              if (intValue == null) return nullConstant;
-              if (targetingJavaScript) {
-                return canonicalize(new JavaScriptIntConstant(intValue));
+              Constant intConstant;
+              if (intValue != null) {
+                bool negated = value.startsWith('-');
+                intConstant =
+                    intFolder.makeIntConstant(intValue, unsigned: !negated);
+              } else if (intFolder.isInt(defaultValue)) {
+                intConstant = defaultValue;
+              } else {
+                intConstant = nullConstant;
               }
-              return canonicalize(new IntConstant(intValue));
+              return canonicalize(intConstant);
             } else if (target.enclosingClass == coreTypes.stringClass) {
               value ??=
                   defaultValue is StringConstant ? defaultValue.value : null;
@@ -1829,16 +1698,10 @@
         final Constant right = positionals[1];
 
         if (targetingJavaScript) {
-          // In JavaScript, we lower [identical] to `===`, so any comparison
-          // against NaN yields `false`.
-          if (isNaN(left) || isNaN(right)) {
-            return falseConstant;
-          }
-
-          // In JavaScript, `-0.0 === 0.0`.
-          if (isZero(left)) {
-            return makeBoolConstant(isZero(right));
-          }
+          // In JavaScript, we lower [identical] to `===`, so we need to take
+          // the double special cases into account.
+          return doubleSpecialCases(left, right) ??
+              makeBoolConstant(identical(left, right));
         }
 
         // Since we canonicalize constants during the evaluation, we can use
@@ -1948,16 +1811,19 @@
 
   // Helper methods:
 
-  bool isZero(Constant value) =>
-      (value is IntConstant && value.value == 0) ||
-      (value is JavaScriptIntConstant && value.bigIntValue == BigInt.zero) ||
-      (value is DoubleConstant && value.value == 0);
-
-  bool isNaN(Constant value) => value is DoubleConstant && value.value.isNaN;
+  /// If both constants are DoubleConstant whose values would give different
+  /// results from == and [identical], return the result of ==. Otherwise
+  /// return null.
+  Constant doubleSpecialCases(Constant a, Constant b) {
+    if (a is DoubleConstant && b is DoubleConstant) {
+      if (a.value.isNaN && b.value.isNaN) return falseConstant;
+      if (a.value == 0.0 && b.value == 0.0) return trueConstant;
+    }
+    return null;
+  }
 
   bool hasPrimitiveEqual(Constant constant) {
-    // TODO(askesc, fishythefish): Make sure the correct class is inferred
-    // when we clean up JavaScript int constant handling.
+    if (intFolder.isInt(constant)) return true;
     DartType type = constant.getType(typeEnvironment);
     return !(type is InterfaceType && !classHasPrimitiveEqual(type.classNode));
   }
@@ -1981,18 +1847,6 @@
   BoolConstant makeBoolConstant(bool value) =>
       value ? trueConstant : falseConstant;
 
-  DoubleConstant makeDoubleConstant(double value) {
-    if (targetingJavaScript) {
-      // Convert to an integer when possible (matching the runtime behavior
-      // of `is int`).
-      if (value.isFinite && !identical(value, -0.0)) {
-        int i = value.toInt();
-        if (value == i.toDouble()) return new JavaScriptIntConstant(i);
-      }
-    }
-    return new DoubleConstant(value);
-  }
-
   bool isSubtype(Constant constant, DartType type) {
     DartType constantType = constant.getType(typeEnvironment);
     if (targetingJavaScript) {
@@ -2106,88 +1960,26 @@
     }
   }
 
-  Constant evaluateBinaryBitOperation(String op, int a, int b, TreeNode node) {
-    int result;
-    switch (op) {
-      case '|':
-        result = a | b;
-        break;
-      case '&':
-        result = a & b;
-        break;
-      case '^':
-        result = a ^ b;
-        break;
-    }
-
-    if (targetingJavaScript) {
-      return canonicalize(new JavaScriptIntConstant(result));
-    }
-    return canonicalize(new IntConstant(result));
-  }
-
-  Constant evaluateBinaryShiftOperation(String op, int a, int b, TreeNode node,
-      {negativeReceiver: false}) {
-    int result;
-    switch (op) {
-      case '<<':
-        result = a << b;
-        break;
-      case '>>':
-        if (targetingJavaScript) {
-          if (negativeReceiver) {
-            const int signBit = 0x80000000;
-            a -= (a & signBit) << 1;
-          }
-          result = a >> b;
-        } else {
-          result = a >> b;
-        }
-        break;
-      case '>>>':
-        // TODO(fishythefish): Implement JS semantics for `>>>`.
-        result = b >= 64 ? 0 : (a >> b) & ((1 << (64 - b)) - 1);
-        break;
-    }
-
-    if (targetingJavaScript) {
-      return canonicalize(new JavaScriptIntConstant(result.toUnsigned(32)));
-    }
-    return canonicalize(new IntConstant(result));
-  }
-
+  /// Binary operation between two operands, at least one of which is a double.
   Constant evaluateBinaryNumericOperation(
       String op, num a, num b, TreeNode node) {
-    num result;
     switch (op) {
       case '+':
-        result = a + b;
-        break;
+        return new DoubleConstant(a + b);
       case '-':
-        result = a - b;
-        break;
+        return new DoubleConstant(a - b);
       case '*':
-        result = a * b;
-        break;
+        return new DoubleConstant(a * b);
       case '/':
-        result = a / b;
-        break;
+        return new DoubleConstant(a / b);
       case '~/':
-        result = a ~/ b;
-        break;
+        if (b == 0) {
+          return report(
+              node, templateConstEvalZeroDivisor.withArguments(op, '$a'));
+        }
+        return intFolder.truncatingDivide(a, b);
       case '%':
-        result = a % b;
-        break;
-    }
-
-    if (result is int) {
-      if (targetingJavaScript) {
-        return canonicalize(new JavaScriptIntConstant(result));
-      }
-      return canonicalize(new IntConstant(result.toSigned(64)));
-    }
-    if (result is double) {
-      return canonicalize(makeDoubleConstant(result));
+        return new DoubleConstant(a % b);
     }
 
     switch (op) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_int_folder.dart b/pkg/front_end/lib/src/fasta/kernel/constant_int_folder.dart
new file mode 100644
index 0000000..e28900f
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_int_folder.dart
@@ -0,0 +1,238 @@
+// 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:core' hide MapEntry;
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/target/targets.dart';
+
+import 'constant_evaluator.dart';
+
+import '../fasta_codes.dart'
+    show
+        templateConstEvalInvalidMethodInvocation,
+        templateConstEvalNegativeShift,
+        templateConstEvalZeroDivisor;
+
+abstract class ConstantIntFolder {
+  final ConstantEvaluator evaluator;
+
+  ConstantIntFolder(this.evaluator);
+
+  factory ConstantIntFolder.forSemantics(
+      ConstantEvaluator evaluator, NumberSemantics semantics) {
+    if (semantics == NumberSemantics.js) {
+      return new JsConstantIntFolder(evaluator);
+    } else {
+      return new VmConstantIntFolder(evaluator);
+    }
+  }
+
+  bool isInt(Constant constant);
+
+  Constant makeIntConstant(int value, {bool unsigned: false});
+
+  Constant foldUnaryOperator(
+      MethodInvocation node, String op, covariant Constant operand);
+
+  Constant foldBinaryOperator(MethodInvocation node, String op,
+      covariant Constant left, covariant Constant right);
+
+  Constant truncatingDivide(num left, num right);
+
+  void _checkOperands(MethodInvocation node, String op, num left, num right) {
+    if ((op == '<<' || op == '>>' || op == '>>>') && right < 0) {
+      evaluator.report(node,
+          templateConstEvalNegativeShift.withArguments(op, '$left', '$right'));
+    }
+    if ((op == '%' || op == '~/') && right == 0) {
+      evaluator.report(
+          node, templateConstEvalZeroDivisor.withArguments(op, '$left'));
+    }
+  }
+}
+
+class VmConstantIntFolder extends ConstantIntFolder {
+  VmConstantIntFolder(ConstantEvaluator evaluator) : super(evaluator);
+
+  @override
+  bool isInt(Constant constant) => constant is IntConstant;
+
+  @override
+  IntConstant makeIntConstant(int value, {bool unsigned: false}) {
+    return new IntConstant(value);
+  }
+
+  @override
+  Constant foldUnaryOperator(
+      MethodInvocation node, String op, IntConstant operand) {
+    switch (op) {
+      case 'unary-':
+        return new IntConstant(-operand.value);
+      case '~':
+        return new IntConstant(~operand.value);
+      default:
+        return evaluator.report(
+            node,
+            templateConstEvalInvalidMethodInvocation.withArguments(
+                op, operand));
+    }
+  }
+
+  @override
+  Constant foldBinaryOperator(
+      MethodInvocation node, String op, IntConstant left, IntConstant right) {
+    int a = left.value;
+    int b = right.value;
+    _checkOperands(node, op, a, b);
+    switch (op) {
+      case '+':
+        return new IntConstant(a + b);
+      case '-':
+        return new IntConstant(a - b);
+      case '*':
+        return new IntConstant(a * b);
+      case '/':
+        return new DoubleConstant(a / b);
+      case '~/':
+        return new IntConstant(a ~/ b);
+      case '%':
+        return new IntConstant(a % b);
+      case '|':
+        return new IntConstant(a | b);
+      case '&':
+        return new IntConstant(a & b);
+      case '^':
+        return new IntConstant(a ^ b);
+      case '<<':
+        return new IntConstant(a << b);
+      case '>>':
+        return new IntConstant(a >> b);
+      case '>>>':
+        int result = b >= 64 ? 0 : (a >> b) & ((1 << (64 - b)) - 1);
+        return new IntConstant(result);
+      case '<':
+        return evaluator.makeBoolConstant(a < b);
+      case '<=':
+        return evaluator.makeBoolConstant(a <= b);
+      case '>=':
+        return evaluator.makeBoolConstant(a >= b);
+      case '>':
+        return evaluator.makeBoolConstant(a > b);
+      default:
+        return evaluator.report(node,
+            templateConstEvalInvalidMethodInvocation.withArguments(op, left));
+    }
+  }
+
+  @override
+  Constant truncatingDivide(num left, num right) {
+    return new IntConstant(left ~/ right);
+  }
+}
+
+class JsConstantIntFolder extends ConstantIntFolder {
+  JsConstantIntFolder(ConstantEvaluator evaluator) : super(evaluator);
+
+  static bool _valueIsInteger(double value) {
+    return value.isFinite && value.truncateToDouble() == value;
+  }
+
+  static int _truncate32(int value) => value & 0xFFFFFFFF;
+
+  static int _toUint32(double value) {
+    return new BigInt.from(value).toUnsigned(32).toInt();
+  }
+
+  @override
+  bool isInt(Constant constant) {
+    return constant is DoubleConstant && _valueIsInteger(constant.value);
+  }
+
+  @override
+  DoubleConstant makeIntConstant(int value, {bool unsigned: false}) {
+    double doubleValue = value.toDouble();
+    assert(doubleValue.toInt() == value);
+    if (unsigned) {
+      const double twoTo64 = 18446744073709551616.0;
+      if (value < 0) doubleValue += twoTo64;
+    }
+    return new DoubleConstant(doubleValue);
+  }
+
+  @override
+  Constant foldUnaryOperator(
+      MethodInvocation node, String op, DoubleConstant operand) {
+    switch (op) {
+      case 'unary-':
+        return new DoubleConstant(-operand.value);
+      case '~':
+        int intValue = _toUint32(operand.value);
+        return new DoubleConstant(_truncate32(~intValue).toDouble());
+      default:
+        return evaluator.report(
+            node,
+            templateConstEvalInvalidMethodInvocation.withArguments(
+                op, operand));
+    }
+  }
+
+  @override
+  Constant foldBinaryOperator(MethodInvocation node, String op,
+      DoubleConstant left, DoubleConstant right) {
+    double a = left.value;
+    double b = right.value;
+    _checkOperands(node, op, a, b);
+    switch (op) {
+      case '+':
+        return new DoubleConstant(a + b);
+      case '-':
+        return new DoubleConstant(a - b);
+      case '*':
+        return new DoubleConstant(a * b);
+      case '/':
+        return new DoubleConstant(a / b);
+      case '~/':
+        return truncatingDivide(a, b);
+      case '%':
+        return new DoubleConstant(a % b);
+      case '|':
+        return new DoubleConstant((_toUint32(a) | _toUint32(b)).toDouble());
+      case '&':
+        return new DoubleConstant((_toUint32(a) & _toUint32(b)).toDouble());
+      case '^':
+        return new DoubleConstant((_toUint32(a) ^ _toUint32(b)).toDouble());
+      case '<<':
+        int ai = _toUint32(a);
+        return new DoubleConstant(_truncate32(ai << b.toInt()).toDouble());
+      case '>>':
+        int ai = _toUint32(a);
+        if (a < 0) {
+          const int signBit = 0x80000000;
+          ai -= (ai & signBit) << 1;
+        }
+        return new DoubleConstant(_truncate32(ai >> b.toInt()).toDouble());
+      case '>>>':
+        int ai = _toUint32(a);
+        return new DoubleConstant(_truncate32(ai >> b.toInt()).toDouble());
+      case '<':
+        return evaluator.makeBoolConstant(a < b);
+      case '<=':
+        return evaluator.makeBoolConstant(a <= b);
+      case '>=':
+        return evaluator.makeBoolConstant(a >= b);
+      case '>':
+        return evaluator.makeBoolConstant(a > b);
+      default:
+        return evaluator.report(node,
+            templateConstEvalInvalidMethodInvocation.withArguments(op, left));
+    }
+  }
+
+  @override
+  Constant truncatingDivide(num left, num right) {
+    double result = (left / right).truncateToDouble();
+    return new DoubleConstant(result == 0.0 ? 0.0 : result);
+  }
+}
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 69994cc..de53658 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -7,23 +7,7 @@
 
 import 'dart:core' hide MapEntry;
 
-import 'package:kernel/ast.dart'
-    show
-        Constructor,
-        Field,
-        IntLiteral,
-        InvalidExpression,
-        Let,
-        Node,
-        PropertyGet,
-        PropertySet,
-        StaticSet,
-        SuperMethodInvocation,
-        SuperPropertySet,
-        TreeNode,
-        TypeParameter,
-        VariableGet,
-        VariableSet;
+import 'package:kernel/ast.dart';
 
 import '../../scanner/token.dart' show Token;
 
@@ -99,19 +83,7 @@
         UnlinkedDeclaration,
         UnresolvedType;
 
-import 'kernel_shadow_ast.dart'
-    show
-        ComplexAssignmentJudgment,
-        LoadLibraryTearOffJudgment,
-        MethodInvocationJudgment,
-        NullAwarePropertyGetJudgment,
-        PropertyAssignmentJudgment,
-        SuperMethodInvocationJudgment,
-        SuperPropertyGetJudgment,
-        SyntheticWrapper,
-        VariableDeclarationJudgment,
-        VariableGetJudgment,
-        getExplicitTypeArguments;
+import 'kernel_shadow_ast.dart';
 
 /// A generator represents a subexpression for which we can't yet build an
 /// expression because we don't yet know the context in which it's used.
@@ -196,8 +168,7 @@
   /// [voidContext] is true, in which case it may evaluate to anything.
   ///
   /// [type] is the static type of the RHS.
-  Expression buildNullAwareAssignment(
-      Expression value, DartType type, int offset,
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
       {bool voidContext: false}) {
     ComplexAssignmentJudgment complexAssignment = startComplexAssignment(value);
     if (voidContext) {
@@ -281,9 +252,8 @@
         offset: offset);
     complexAssignment?.combiner = combiner;
     complexAssignment?.isPostIncDec = true;
-    VariableDeclarationJudgment dummy =
-        new VariableDeclarationJudgment.forValue(
-            _makeWrite(combiner, true, complexAssignment));
+    VariableDeclarationImpl dummy = new VariableDeclarationImpl.forValue(
+        _makeWrite(combiner, true, complexAssignment));
     return _finish(
         makeLet(value, makeLet(dummy, valueAccess())), complexAssignment);
   }
@@ -372,7 +342,7 @@
 
   Expression _finish(
       Expression body, ComplexAssignmentJudgment complexAssignment) {
-    if (!_helper.legacyMode && complexAssignment != null) {
+    if (complexAssignment != null) {
       complexAssignment.desugared = body;
       return complexAssignment;
     } else {
@@ -517,17 +487,85 @@
   String get _plainNameForRead => variable.name;
 
   @override
+  Expression buildSimpleRead() {
+    return _createRead();
+  }
+
+  Expression _createRead() {
+    return _helper.createVariableGet(variable, fileOffset);
+  }
+
+  @override
   Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
     TypePromotionFact fact = _helper.typePromoter
         ?.getFactForAccess(variable, _helper.functionNestingLevel);
     TypePromotionScope scope = _helper.typePromoter?.currentScope;
-    VariableGetJudgment read = new VariableGetJudgment(variable, fact, scope)
+    VariableGetImpl read = new VariableGetImpl(variable, fact, scope)
       ..fileOffset = fileOffset;
     complexAssignment?.read = read;
     return read;
   }
 
   @override
+  Expression buildAssignment(Expression value, {bool voidContext: false}) {
+    return _createWrite(fileOffset, value);
+  }
+
+  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;
+  }
+
+  Expression buildCompoundAssignment(Name binaryOperator, Expression value,
+      {int offset: TreeNode.noOffset,
+      bool voidContext: false,
+      Procedure interfaceTarget,
+      bool isPreIncDec: false,
+      bool isPostIncDec: false}) {
+    MethodInvocation binary = _helper.forest.createMethodInvocation(
+        offset,
+        _createRead(),
+        binaryOperator,
+        _helper.forest.createArguments(offset, <Expression>[value]),
+        interfaceTarget: interfaceTarget);
+    return _createWrite(fileOffset, binary);
+  }
+
+  @override
+  Expression buildPostfixIncrement(Name binaryOperator,
+      {int offset = TreeNode.noOffset,
+      bool voidContext = false,
+      Procedure interfaceTarget}) {
+    Expression value = _forest.createIntLiteral(1, null)..fileOffset = offset;
+    if (voidContext) {
+      return buildCompoundAssignment(binaryOperator, value,
+          offset: offset,
+          voidContext: voidContext,
+          interfaceTarget: interfaceTarget,
+          isPostIncDec: true);
+    }
+    VariableDeclaration read = _helper.forest
+        .createVariableDeclarationForValue(fileOffset, _createRead());
+    MethodInvocation binary = _helper.forest.createMethodInvocation(
+        offset,
+        _helper.createVariableGet(read, fileOffset),
+        binaryOperator,
+        _helper.forest.createArguments(offset, <Expression>[value]),
+        interfaceTarget: interfaceTarget);
+    VariableDeclaration write = _helper.forest
+        .createVariableDeclarationForValue(
+            offset, _createWrite(offset, binary));
+    return new LocalPostIncDec(read, write)..fileOffset = offset;
+  }
+
+  @override
   Expression _makeWrite(Expression value, bool voidContext,
       ComplexAssignmentJudgment complexAssignment) {
     _helper.typePromoter
@@ -646,6 +684,87 @@
   }
 
   @override
+  Expression buildAssignment(Expression value, {bool voidContext: false}) {
+    return new PropertySet(receiver, name, value, setter)
+      ..fileOffset = fileOffset;
+  }
+
+  @override
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
+      {bool voidContext = false}) {
+    VariableDeclaration variable = _helper.forest
+        .createVariableDeclarationForValue(receiver.fileOffset, receiver);
+    PropertyGet read = new PropertyGet(
+        _helper.createVariableGet(variable, receiver.fileOffset), name)
+      ..fileOffset = fileOffset;
+    PropertySet write = new PropertySet(
+        _helper.createVariableGet(variable, receiver.fileOffset), name, value)
+      ..fileOffset = fileOffset;
+    return new IfNullPropertySet(variable, read, write, forEffect: voidContext)
+      ..fileOffset = offset;
+  }
+
+  @override
+  Expression buildCompoundAssignment(Name binaryOperator, Expression value,
+      {int offset: TreeNode.noOffset,
+      bool voidContext: false,
+      Procedure interfaceTarget,
+      bool isPreIncDec: false,
+      bool isPostIncDec: false}) {
+    VariableDeclaration variable = _helper.forest
+        .createVariableDeclarationForValue(receiver.fileOffset, 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 = new PropertySet(
+        _helper.createVariableGet(variable, receiver.fileOffset), name, binary)
+      ..fileOffset = fileOffset;
+    return new CompoundPropertySet(variable, write)..fileOffset = offset;
+  }
+
+  @override
+  Expression buildPostfixIncrement(Name binaryOperator,
+      {int offset = TreeNode.noOffset,
+      bool voidContext = false,
+      Procedure interfaceTarget}) {
+    Expression value = _forest.createIntLiteral(1, null)..fileOffset = offset;
+    if (voidContext) {
+      return buildCompoundAssignment(binaryOperator, value,
+          offset: offset,
+          voidContext: voidContext,
+          interfaceTarget: interfaceTarget,
+          isPostIncDec: true);
+    }
+    VariableDeclaration variable = _helper.forest
+        .createVariableDeclarationForValue(receiver.fileOffset, receiver);
+    VariableDeclaration read = _helper.forest.createVariableDeclarationForValue(
+        fileOffset,
+        new PropertyGet(
+            _helper.createVariableGet(variable, receiver.fileOffset), name)
+          ..fileOffset = fileOffset);
+    MethodInvocation binary = _helper.forest.createMethodInvocation(
+        offset,
+        _helper.createVariableGet(read, fileOffset),
+        binaryOperator,
+        _helper.forest.createArguments(offset, <Expression>[value]),
+        interfaceTarget: interfaceTarget);
+    VariableDeclaration write = _helper.forest
+        .createVariableDeclarationForValue(
+            offset,
+            new PropertySet(
+                _helper.createVariableGet(variable, receiver.fileOffset),
+                name,
+                binary)
+              ..fileOffset = fileOffset);
+    return new PropertyPostIncDec(variable, read, write)..fileOffset = offset;
+  }
+
+  @override
   Expression _makeSimpleWrite(Expression value, bool voidContext,
       ComplexAssignmentJudgment complexAssignment) {
     PropertySet write = new PropertySet(receiver, name, value, setter)
@@ -760,6 +879,41 @@
   String get _plainNameForRead => name.name;
 
   @override
+  Expression buildSimpleRead() {
+    return _createRead();
+  }
+
+  Expression _createRead() {
+    if (getter == null) {
+      _helper.warnUnresolvedGet(name, fileOffset);
+    }
+    return new PropertyGet(_forest.createThisExpression(token), name, getter)
+      ..fileOffset = fileOffset;
+  }
+
+  @override
+  Expression buildAssignment(Expression value, {bool voidContext: false}) {
+    return _createWrite(fileOffset, value);
+  }
+
+  Expression _createWrite(int offset, Expression value) {
+    if (setter == null) {
+      _helper.warnUnresolvedSet(name, fileOffset);
+    }
+    return new PropertySet(
+        _forest.createThisExpression(token), name, value, setter)
+      ..fileOffset = fileOffset;
+  }
+
+  @override
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
+      {bool voidContext: false}) {
+    return new IfNullSet(_createRead(), _createWrite(offset, value),
+        forEffect: voidContext)
+      ..fileOffset = offset;
+  }
+
+  @override
   Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
     if (getter == null) {
       _helper.warnUnresolvedGet(name, fileOffset);
@@ -849,6 +1003,33 @@
   String get _plainNameForRead => name.name;
 
   @override
+  Expression buildSimpleRead() {
+    VariableDeclaration variable = _helper.forest
+        .createVariableDeclarationForValue(
+            receiverExpression.fileOffset, receiverExpression);
+    PropertyGet read = new PropertyGet(
+        _helper.createVariableGet(variable, receiverExpression.fileOffset),
+        name)
+      ..fileOffset = fileOffset;
+    return new NullAwarePropertyGet(variable, read)
+      ..fileOffset = receiverExpression.fileOffset;
+  }
+
+  @override
+  Expression buildAssignment(Expression value, {bool voidContext = false}) {
+    VariableDeclaration variable = _helper.forest
+        .createVariableDeclarationForValue(
+            receiverExpression.fileOffset, receiverExpression);
+    PropertySet read = new PropertySet(
+        _helper.createVariableGet(variable, receiverExpression.fileOffset),
+        name,
+        value)
+      ..fileOffset = fileOffset;
+    return new NullAwarePropertySet(variable, read)
+      ..fileOffset = receiverExpression.fileOffset;
+  }
+
+  @override
   Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
     PropertyGet read = new PropertyGet(receiverAccess(), name, getter)
       ..fileOffset = fileOffset;
@@ -877,14 +1058,12 @@
       ..fileOffset = fileOffset;
     if (complexAssignment != null) {
       body = makeLet(receiver, nullAwareGuard);
-      if (_helper.legacyMode) return body;
       PropertyAssignmentJudgment kernelPropertyAssign = complexAssignment;
       kernelPropertyAssign.nullAwareGuard = nullAwareGuard;
       kernelPropertyAssign.desugared = body;
       return kernelPropertyAssign;
     } else {
-      return new NullAwarePropertyGetJudgment(receiver, nullAwareGuard)
-        ..fileOffset = fileOffset;
+      return unhandled('${runtimeType}', "_finish", fileOffset, _uri);
     }
   }
 
@@ -933,19 +1112,95 @@
   String get _plainNameForRead => name.name;
 
   @override
+  Expression buildSimpleRead() {
+    return _createRead();
+  }
+
+  Expression _createRead() {
+    if (getter == null) {
+      _helper.warnUnresolvedGet(name, fileOffset, isSuper: true);
+    }
+    return new SuperPropertyGet(name, getter)..fileOffset = fileOffset;
+  }
+
+  @override
   Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
     if (getter == null) {
       _helper.warnUnresolvedGet(name, fileOffset, isSuper: true);
     }
     // TODO(ahe): Use [DirectPropertyGet] when possible.
-    SuperPropertyGetJudgment read =
-        new SuperPropertyGetJudgment(name, interfaceTarget: getter)
-          ..fileOffset = fileOffset;
+    SuperPropertyGet read = new SuperPropertyGet(name, getter)
+      ..fileOffset = fileOffset;
     complexAssignment?.read = read;
     return read;
   }
 
   @override
+  Expression buildAssignment(Expression value, {bool voidContext = false}) {
+    return _createWrite(fileOffset, value);
+  }
+
+  Expression _createWrite(int offset, Expression value) {
+    if (setter == null) {
+      _helper.warnUnresolvedSet(name, offset, isSuper: true);
+    }
+    SuperPropertySet write = new SuperPropertySet(name, value, setter)
+      ..fileOffset = offset;
+    return write;
+  }
+
+  @override
+  Expression buildCompoundAssignment(Name binaryOperator, Expression value,
+      {int offset = TreeNode.noOffset,
+      bool voidContext = false,
+      Procedure interfaceTarget,
+      bool isPreIncDec = false,
+      bool isPostIncDec = false}) {
+    MethodInvocation binary = _helper.forest.createMethodInvocation(
+        offset,
+        _createRead(),
+        binaryOperator,
+        _helper.forest.createArguments(offset, <Expression>[value]),
+        interfaceTarget: interfaceTarget);
+    return _createWrite(fileOffset, binary);
+  }
+
+  @override
+  Expression buildPostfixIncrement(Name binaryOperator,
+      {int offset = TreeNode.noOffset,
+      bool voidContext = false,
+      Procedure interfaceTarget}) {
+    Expression value = _forest.createIntLiteral(1, null)..fileOffset = offset;
+    if (voidContext) {
+      return buildCompoundAssignment(binaryOperator, value,
+          offset: offset,
+          voidContext: voidContext,
+          interfaceTarget: interfaceTarget,
+          isPostIncDec: true);
+    }
+    VariableDeclaration read = _helper.forest
+        .createVariableDeclarationForValue(fileOffset, _createRead());
+    MethodInvocation binary = _helper.forest.createMethodInvocation(
+        offset,
+        _helper.createVariableGet(read, fileOffset),
+        binaryOperator,
+        _helper.forest.createArguments(offset, <Expression>[value]),
+        interfaceTarget: interfaceTarget);
+    VariableDeclaration write = _helper.forest
+        .createVariableDeclarationForValue(
+            offset, _createWrite(fileOffset, binary));
+    return new StaticPostIncDec(read, write)..fileOffset = offset;
+  }
+
+  @override
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
+      {bool voidContext: false}) {
+    return new IfNullSet(_createRead(), _createWrite(fileOffset, value),
+        forEffect: voidContext)
+      ..fileOffset = offset;
+  }
+
+  @override
   Expression _makeWrite(Expression value, bool voidContext,
       ComplexAssignmentJudgment complexAssignment) {
     if (setter == null) {
@@ -1017,6 +1272,66 @@
   @override
   String get _debugName => "IndexedAccessGenerator";
 
+  @override
+  Expression buildSimpleRead() {
+    return _helper.buildMethodInvocation(
+        receiver,
+        new Name('[]'),
+        _helper.forest.createArguments(fileOffset, <Expression>[index]),
+        fileOffset,
+        interfaceTarget: getter);
+  }
+
+  @override
+  Expression buildAssignment(Expression value, {bool voidContext: false}) {
+    if (voidContext) {
+      return _helper.buildMethodInvocation(
+          receiver,
+          new Name('[]='),
+          _helper.forest
+              .createArguments(fileOffset, <Expression>[index, value]),
+          fileOffset,
+          interfaceTarget: setter);
+    } else {
+      return new IndexSet(receiver, index, value)..fileOffset = fileOffset;
+    }
+  }
+
+  @override
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
+      {bool voidContext: false}) {
+    return new IfNullIndexSet(receiver, index, value, fileOffset,
+        forEffect: voidContext)
+      ..fileOffset = offset;
+  }
+
+  Expression buildCompoundAssignment(Name binaryOperator, Expression value,
+      {int offset: TreeNode.noOffset,
+      bool voidContext: false,
+      Procedure interfaceTarget,
+      bool isPreIncDec: false,
+      bool isPostIncDec: false}) {
+    return new CompoundIndexSet(receiver, index, binaryOperator, value,
+        readOffset: fileOffset,
+        binaryOffset: offset,
+        writeOffset: fileOffset,
+        forEffect: voidContext,
+        forPostIncDec: isPostIncDec);
+  }
+
+  @override
+  Expression buildPostfixIncrement(Name binaryOperator,
+      {int offset = TreeNode.noOffset,
+      bool voidContext = false,
+      Procedure interfaceTarget}) {
+    Expression value = _forest.createIntLiteral(1, null)..fileOffset = offset;
+    return buildCompoundAssignment(binaryOperator, value,
+        offset: offset,
+        voidContext: voidContext,
+        interfaceTarget: interfaceTarget,
+        isPostIncDec: true);
+  }
+
   Expression indexAccess() {
     indexVariable ??= new VariableDeclaration.forValue(index);
     return new VariableGet(indexVariable)..fileOffset = fileOffset;
@@ -1031,8 +1346,8 @@
 
   @override
   Expression _makeSimpleRead() {
-    MethodInvocationJudgment read = new MethodInvocationJudgment(receiver,
-        indexGetName, _forest.createArguments(fileOffset, <Expression>[index]),
+    MethodInvocationImpl read = new MethodInvocationImpl(receiver, indexGetName,
+        _forest.createArguments(fileOffset, <Expression>[index]),
         interfaceTarget: getter)
       ..fileOffset = fileOffset;
     return read;
@@ -1042,7 +1357,7 @@
   Expression _makeSimpleWrite(Expression value, bool voidContext,
       ComplexAssignmentJudgment complexAssignment) {
     if (!voidContext) return _makeWriteAndReturn(value, complexAssignment);
-    MethodInvocationJudgment write = new MethodInvocationJudgment(
+    MethodInvocationImpl write = new MethodInvocationImpl(
         receiver,
         indexSetName,
         _forest.createArguments(fileOffset, <Expression>[index, value]),
@@ -1054,7 +1369,7 @@
 
   @override
   Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
-    MethodInvocationJudgment read = new MethodInvocationJudgment(
+    MethodInvocationImpl read = new MethodInvocationImpl(
         receiverAccess(),
         indexGetName,
         _forest.createArguments(fileOffset, <Expression>[indexAccess()]),
@@ -1068,7 +1383,7 @@
   Expression _makeWrite(Expression value, bool voidContext,
       ComplexAssignmentJudgment complexAssignment) {
     if (!voidContext) return _makeWriteAndReturn(value, complexAssignment);
-    MethodInvocationJudgment write = new MethodInvocationJudgment(
+    MethodInvocationImpl write = new MethodInvocationImpl(
         receiverAccess(),
         indexSetName,
         _forest.createArguments(fileOffset, <Expression>[indexAccess(), value]),
@@ -1085,7 +1400,7 @@
     // The call to []= does not return the value like direct-style assignments
     // do.  We need to bind the value in a let.
     VariableDeclaration valueVariable = new VariableDeclaration.forValue(value);
-    MethodInvocationJudgment write = new MethodInvocationJudgment(
+    MethodInvocationImpl write = new MethodInvocationImpl(
         receiverAccess(),
         indexSetName,
         _forest.createArguments(fileOffset,
@@ -1093,8 +1408,7 @@
         interfaceTarget: setter)
       ..fileOffset = fileOffset;
     complexAssignment?.write = write;
-    VariableDeclarationJudgment dummy =
-        new VariableDeclarationJudgment.forValue(write);
+    VariableDeclarationImpl dummy = new VariableDeclarationImpl.forValue(write);
     return makeLet(
         valueVariable, makeLet(dummy, new VariableGet(valueVariable)));
   }
@@ -1183,7 +1497,7 @@
   Expression _makeWriteAndReturn(
       Expression value, ComplexAssignmentJudgment complexAssignment) {
     VariableDeclaration valueVariable = new VariableDeclaration.forValue(value);
-    MethodInvocationJudgment write = new MethodInvocationJudgment(
+    MethodInvocationImpl write = new MethodInvocationImpl(
         _forest.createThisExpression(token),
         indexSetName,
         _forest.createArguments(fileOffset,
@@ -1198,7 +1512,7 @@
 
   @override
   Expression _makeSimpleRead() {
-    return new MethodInvocationJudgment(_forest.createThisExpression(token),
+    return new MethodInvocationImpl(_forest.createThisExpression(token),
         indexGetName, _forest.createArguments(fileOffset, <Expression>[index]),
         interfaceTarget: getter)
       ..fileOffset = fileOffset;
@@ -1208,7 +1522,7 @@
   Expression _makeSimpleWrite(Expression value, bool voidContext,
       ComplexAssignmentJudgment complexAssignment) {
     if (!voidContext) return _makeWriteAndReturn(value, complexAssignment);
-    MethodInvocationJudgment write = new MethodInvocationJudgment(
+    MethodInvocationImpl write = new MethodInvocationImpl(
         _forest.createThisExpression(token),
         indexSetName,
         _forest.createArguments(fileOffset, <Expression>[index, value]),
@@ -1220,7 +1534,7 @@
 
   @override
   Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
-    MethodInvocationJudgment read = new MethodInvocationJudgment(
+    MethodInvocationImpl read = new MethodInvocationImpl(
         _forest.createThisExpression(token),
         indexGetName,
         _forest.createArguments(fileOffset, <Expression>[indexAccess()]),
@@ -1234,7 +1548,7 @@
   Expression _makeWrite(Expression value, bool voidContext,
       ComplexAssignmentJudgment complexAssignment) {
     if (!voidContext) return _makeWriteAndReturn(value, complexAssignment);
-    MethodInvocationJudgment write = new MethodInvocationJudgment(
+    MethodInvocationImpl write = new MethodInvocationImpl(
         _forest.createThisExpression(token),
         indexSetName,
         _forest.createArguments(fileOffset, <Expression>[indexAccess(), value]),
@@ -1321,9 +1635,8 @@
       _helper.warnUnresolvedMethod(indexGetName, fileOffset, isSuper: true);
     }
     // TODO(ahe): Use [DirectMethodInvocation] when possible.
-    return new SuperMethodInvocationJudgment(
-        indexGetName, _forest.createArguments(fileOffset, <Expression>[index]),
-        interfaceTarget: getter)
+    return new SuperMethodInvocation(indexGetName,
+        _forest.createArguments(fileOffset, <Expression>[index]), getter)
       ..fileOffset = fileOffset;
   }
 
@@ -1488,6 +1801,87 @@
   String get _plainNameForRead => (readTarget ?? writeTarget).name.name;
 
   @override
+  Expression buildSimpleRead() {
+    return _createRead();
+  }
+
+  Expression _createRead() {
+    Expression read;
+    if (readTarget == null) {
+      read = _makeInvalidRead();
+    } else {
+      read = _helper.makeStaticGet(readTarget, token);
+    }
+    return read;
+  }
+
+  @override
+  Expression buildAssignment(Expression value, {bool voidContext = false}) {
+    return _createWrite(fileOffset, value);
+  }
+
+  Expression _createWrite(int offset, Expression value) {
+    Expression write;
+    if (writeTarget == null) {
+      write = _makeInvalidWrite(value);
+    } else {
+      write = new StaticSet(writeTarget, value)..fileOffset = offset;
+    }
+    return write;
+  }
+
+  @override
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
+      {bool voidContext: false}) {
+    return new IfNullSet(_createRead(), _createWrite(offset, value),
+        forEffect: voidContext)
+      ..fileOffset = offset;
+  }
+
+  @override
+  Expression buildCompoundAssignment(Name binaryOperator, Expression value,
+      {int offset = TreeNode.noOffset,
+      bool voidContext = false,
+      Procedure interfaceTarget,
+      bool isPreIncDec = false,
+      bool isPostIncDec = false}) {
+    MethodInvocation binary = _helper.forest.createMethodInvocation(
+        offset,
+        _createRead(),
+        binaryOperator,
+        _helper.forest.createArguments(offset, <Expression>[value]),
+        interfaceTarget: interfaceTarget);
+    return _createWrite(fileOffset, binary);
+  }
+
+  @override
+  Expression buildPostfixIncrement(Name binaryOperator,
+      {int offset = TreeNode.noOffset,
+      bool voidContext = false,
+      Procedure interfaceTarget}) {
+    Expression value = _forest.createIntLiteral(1, null)..fileOffset = offset;
+    if (voidContext) {
+      return buildCompoundAssignment(binaryOperator, value,
+          offset: offset,
+          voidContext: voidContext,
+          interfaceTarget: interfaceTarget,
+          isPostIncDec: true);
+    }
+    VariableDeclaration read = _helper.forest
+        .createVariableDeclarationForValue(fileOffset, _createRead());
+    MethodInvocation binary = _helper.forest.createMethodInvocation(
+        offset,
+        _helper.createVariableGet(read, fileOffset),
+        binaryOperator,
+        _helper.forest.createArguments(offset, <Expression>[value]),
+        interfaceTarget: interfaceTarget);
+    VariableDeclaration write = _helper.forest
+        .createVariableDeclarationForValue(
+            offset, _createWrite(offset, binary));
+    return new StaticPostIncDec(read, write)..fileOffset = offset;
+  }
+
+  @override
   Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
     Expression read;
     if (readTarget == null) {
@@ -2070,7 +2464,7 @@
   @override
   Expression _makeRead(ComplexAssignmentJudgment complexAssignment) {
     builder.importDependency.targetLibrary;
-    LoadLibraryTearOffJudgment read = new LoadLibraryTearOffJudgment(
+    LoadLibraryTearOff read = new LoadLibraryTearOff(
         builder.importDependency, builder.createTearoffMethod(_helper.forest))
       ..fileOffset = fileOffset;
     complexAssignment?.read = read;
@@ -2593,8 +2987,7 @@
   }
 
   @override
-  Expression buildNullAwareAssignment(
-      Expression value, DartType type, int offset,
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
       {bool voidContext: false}) {
     return buildError(_forest.createArguments(fileOffset, <Expression>[value]),
         isSetter: true);
@@ -2789,8 +3182,7 @@
   }
 
   @override
-  Expression buildNullAwareAssignment(
-      Expression value, DartType type, int offset,
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
       {bool voidContext: false}) {
     return _makeInvalidWrite(value);
   }
@@ -2886,7 +3278,7 @@
       return generator.buildCompoundAssignment(tripleShiftName, value,
           offset: fileOffset, voidContext: voidContext);
     } else if (identical("??=", assignmentOperator)) {
-      return generator.buildNullAwareAssignment(
+      return generator.buildIfNullAssignment(
           value, const DynamicType(), fileOffset,
           voidContext: voidContext);
     } else if (identical("^=", assignmentOperator)) {
@@ -3134,8 +3526,7 @@
     return buildProblem();
   }
 
-  Expression buildNullAwareAssignment(
-      Expression value, DartType type, int offset,
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
       {bool voidContext: false}) {
     return buildProblem();
   }
@@ -3395,8 +3786,7 @@
     return buildAssignmentError();
   }
 
-  Expression buildNullAwareAssignment(
-      Expression value, DartType type, int offset,
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
       {bool voidContext: false}) {
     return buildAssignmentError();
   }
@@ -3526,8 +3916,7 @@
         isNullAware: isNullAware);
   }
 
-  Expression buildNullAwareAssignment(
-      Expression value, DartType type, int offset,
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
       {bool voidContext: false}) {
     return unsupported("buildNullAwareAssignment", offset, _uri);
   }
@@ -3601,8 +3990,7 @@
         _helper.toValue(receiver), name, null, null, isNullAware);
   }
 
-  Expression buildNullAwareAssignment(
-      Expression value, DartType type, int offset,
+  Expression buildIfNullAssignment(Expression value, DartType type, int offset,
       {bool voidContext: false}) {
     return unsupported("buildNullAwareAssignment", offset, _uri);
   }
@@ -3673,7 +4061,7 @@
 Expression makeBinary(Expression left, Name operator, Procedure interfaceTarget,
     Expression right, ExpressionGeneratorHelper helper,
     {int offset: TreeNode.noOffset}) {
-  return new MethodInvocationJudgment(left, operator,
+  return new MethodInvocationImpl(left, operator,
       helper.forest.createArguments(offset, <Expression>[right]),
       interfaceTarget: interfaceTarget)
     ..fileOffset = 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 c847440..53d1baf 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
@@ -53,8 +53,6 @@
 
   Forest get forest;
 
-  bool get legacyMode;
-
   Constructor lookupConstructor(Name name, {bool isSuper});
 
   Expression toValue(node);
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index f63bfbc..37926f6 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -28,34 +28,14 @@
 
 import 'kernel_shadow_ast.dart'
     show
-        ArgumentsJudgment,
-        AssertInitializerJudgment,
-        AssertStatementJudgment,
-        BlockJudgment,
-        CatchJudgment,
-        DoJudgment,
-        DoubleJudgment,
-        EmptyStatementJudgment,
-        ExpressionStatementJudgment,
-        ForJudgment,
-        FunctionNodeJudgment,
-        IfJudgment,
+        ArgumentsImpl,
         IntJudgment,
-        ListLiteralJudgment,
-        LoadLibraryJudgment,
-        MapLiteralJudgment,
-        MethodInvocationJudgment,
-        ReturnJudgment,
-        SetLiteralJudgment,
+        LoadLibraryImpl,
+        MethodInvocationImpl,
+        ReturnStatementImpl,
         ShadowLargeIntLiteral,
-        SymbolLiteralJudgment,
         SyntheticExpressionJudgment,
-        TryCatchJudgment,
-        TryFinallyJudgment,
-        TypeLiteralJudgment,
-        VariableDeclarationJudgment,
-        WhileJudgment,
-        YieldJudgment;
+        VariableDeclarationImpl;
 
 /// A shadow tree factory.
 class Forest {
@@ -63,7 +43,7 @@
 
   Arguments createArguments(int fileOffset, List<Expression> positional,
       {List<DartType> types, List<NamedExpression> named}) {
-    return new ArgumentsJudgment(positional, types: types, named: named)
+    return new ArgumentsImpl(positional, types: types, named: named)
       ..fileOffset = fileOffset ?? TreeNode.noOffset;
   }
 
@@ -76,7 +56,7 @@
       List<DartType> typeArguments = const <DartType>[],
       List<Expression> positionalArguments = const <Expression>[],
       List<NamedExpression> namedArguments = const <NamedExpression>[]}) {
-    return new ArgumentsJudgment.forExtensionMethod(
+    return new ArgumentsImpl.forExtensionMethod(
         extensionTypeParameterCount, typeParameterCount, receiver,
         extensionTypeArguments: extensionTypeArguments,
         typeArguments: typeArguments,
@@ -102,7 +82,7 @@
   }
 
   void argumentsSetTypeArguments(Arguments arguments, List<DartType> types) {
-    ArgumentsJudgment.setNonInferrableArgumentTypes(arguments, types);
+    ArgumentsImpl.setNonInferrableArgumentTypes(arguments, types);
   }
 
   StringLiteral asLiteralString(Expression value) => value;
@@ -116,7 +96,7 @@
   /// Return a representation of a double literal at the given [location]. The
   /// literal has the given [value].
   DoubleLiteral createDoubleLiteral(double value, Token token) {
-    return new DoubleJudgment(value)..fileOffset = offsetForToken(token);
+    return new DoubleLiteral(value)..fileOffset = offsetForToken(token);
   }
 
   /// Return a representation of an integer literal at the given [location]. The
@@ -151,7 +131,7 @@
       Token rightBracket) {
     // TODO(brianwilkerson): The file offset computed below will not be correct
     // if there are type arguments but no `const` keyword.
-    return new ListLiteralJudgment(expressions,
+    return new ListLiteral(expressions,
         typeArgument: typeArgument, isConst: isConst)
       ..fileOffset = offsetForToken(constKeyword ?? leftBracket);
   }
@@ -177,7 +157,7 @@
       Token rightBrace) {
     // TODO(brianwilkerson): The file offset computed below will not be correct
     // if there are type arguments but no `const` keyword.
-    return new SetLiteralJudgment(expressions,
+    return new SetLiteral(expressions,
         typeArgument: typeArgument, isConst: isConst)
       ..fileOffset = offsetForToken(constKeyword ?? leftBrace);
   }
@@ -206,7 +186,7 @@
       Token rightBrace) {
     // TODO(brianwilkerson): The file offset computed below will not be correct
     // if there are type arguments but no `const` keyword.
-    return new MapLiteralJudgment(entries,
+    return new MapLiteral(entries,
         keyType: keyType, valueType: valueType, isConst: isConst)
       ..fileOffset = offsetForToken(constKeyword ?? leftBrace);
   }
@@ -225,11 +205,11 @@
 
   /// Return a representation of a symbol literal defined by [value].
   SymbolLiteral createSymbolLiteral(String value, Token token) {
-    return new SymbolLiteralJudgment(value)..fileOffset = offsetForToken(token);
+    return new SymbolLiteral(value)..fileOffset = offsetForToken(token);
   }
 
   TypeLiteral createTypeLiteral(DartType type, Token token) {
-    return new TypeLiteralJudgment(type)..fileOffset = offsetForToken(token);
+    return new TypeLiteral(type)..fileOffset = offsetForToken(token);
   }
 
   /// Return a representation of a key/value pair in a literal map. The [key] is
@@ -244,7 +224,7 @@
 
   Expression createLoadLibrary(
       LibraryDependency dependency, Arguments arguments) {
-    return new LoadLibraryJudgment(dependency, arguments);
+    return new LoadLibraryImpl(dependency, arguments);
   }
 
   Expression checkLibraryIsLoaded(LibraryDependency dependency) {
@@ -328,7 +308,7 @@
       Expression condition,
       Token comma,
       Expression message) {
-    return new AssertInitializerJudgment(createAssertStatement(
+    return new AssertInitializer(createAssertStatement(
         assertKeyword, leftParenthesis, condition, comma, message, null));
   }
 
@@ -368,7 +348,7 @@
         endOffset = conditionLastToken.offset + conditionLastToken.length;
       }
     }
-    return new AssertStatementJudgment(condition,
+    return new AssertStatement(condition,
         conditionStartOffset: startOffset,
         conditionEndOffset: endOffset,
         message: message);
@@ -392,7 +372,7 @@
         copy.add(statement);
       }
     }
-    return new BlockJudgment(copy ?? statements)
+    return new Block(copy ?? statements)
       ..fileOffset = offsetForToken(openBrace);
   }
 
@@ -411,7 +391,7 @@
       VariableDeclaration stackTraceParameter,
       DartType stackTraceType,
       Statement body) {
-    return new CatchJudgment(exceptionParameter, body,
+    return new Catch(exceptionParameter, body,
         guard: exceptionType, stackTrace: stackTraceParameter)
       ..fileOffset = offsetForToken(onKeyword ?? catchKeyword);
   }
@@ -437,19 +417,19 @@
   /// Return a representation of a do statement.
   Statement createDoStatement(Token doKeyword, Statement body,
       Token whileKeyword, Expression condition, Token semicolon) {
-    return new DoJudgment(body, condition)..fileOffset = doKeyword.charOffset;
+    return new DoStatement(body, condition)..fileOffset = doKeyword.charOffset;
   }
 
   /// Return a representation of an expression statement composed from the
   /// [expression] and [semicolon].
   Statement createExpressionStatement(Expression expression, Token semicolon) {
-    return new ExpressionStatementJudgment(expression);
+    return new ExpressionStatement(expression);
   }
 
   /// Return a representation of an empty statement consisting of the given
   /// [semicolon].
   Statement createEmptyStatement(Token semicolon) {
-    return new EmptyStatementJudgment();
+    return new EmptyStatement();
   }
 
   /// Return a representation of a for statement.
@@ -463,14 +443,14 @@
       List<Expression> updaters,
       Token rightParenthesis,
       Statement body) {
-    return new ForJudgment(variables, condition, updaters, body)
+    return new ForStatement(variables ?? [], condition, updaters, body)
       ..fileOffset = forKeyword.charOffset;
   }
 
   /// Return a representation of an `if` statement.
   Statement createIfStatement(Token ifKeyword, Expression condition,
       Statement thenStatement, Token elseKeyword, Statement elseStatement) {
-    return new IfJudgment(condition, thenStatement, elseStatement)
+    return new IfStatement(condition, thenStatement, elseStatement)
       ..fileOffset = ifKeyword.charOffset;
   }
 
@@ -511,14 +491,14 @@
   /// Return a representation of a rethrow statement consisting of the
   /// [rethrowKeyword] followed by the [semicolon].
   Statement createRethrowStatement(Token rethrowKeyword, Token semicolon) {
-    return new ExpressionStatementJudgment(
+    return new ExpressionStatement(
         new Rethrow()..fileOffset = offsetForToken(rethrowKeyword));
   }
 
   /// Return a representation of a return statement.
   Statement createReturnStatement(int fileOffset, Expression expression,
       {bool isArrow: true}) {
-    return new ReturnJudgment(isArrow, expression)
+    return new ReturnStatementImpl(isArrow, expression)
       ..fileOffset = fileOffset ?? TreeNode.noOffset;
   }
 
@@ -559,10 +539,10 @@
       List<Catch> catchClauses, Token finallyKeyword, Statement finallyBlock) {
     Statement result = body;
     if (catchClauses != null) {
-      result = new TryCatchJudgment(result, catchClauses);
+      result = new TryCatch(result, catchClauses);
     }
     if (finallyBlock != null) {
-      result = new TryFinallyJudgment(result, finallyBlock);
+      result = new TryFinally(result, finallyBlock);
     }
     return result;
   }
@@ -579,11 +559,11 @@
 
   Statement wrapVariables(Statement statement) {
     if (statement is _VariablesDeclaration) {
-      return new BlockJudgment(
+      return new Block(
           new List<Statement>.from(statement.declarations, growable: true))
         ..fileOffset = statement.fileOffset;
     } else if (statement is VariableDeclaration) {
-      return new BlockJudgment(<Statement>[statement])
+      return new Block(<Statement>[statement])
         ..fileOffset = statement.fileOffset;
     } else {
       return statement;
@@ -594,7 +574,7 @@
   /// [whileKeyword] and consisting of the given [condition] and [body].
   Statement createWhileStatement(
       Token whileKeyword, Expression condition, Statement body) {
-    return new WhileJudgment(condition, body)
+    return new WhileStatement(condition, body)
       ..fileOffset = whileKeyword.charOffset;
   }
 
@@ -603,7 +583,7 @@
   /// when no star was included in the source code.
   Statement createYieldStatement(
       Token yieldKeyword, Token star, Expression expression, Token semicolon) {
-    return new YieldJudgment(star != null, expression)
+    return new YieldStatement(expression, isYieldStar: star != null)
       ..fileOffset = yieldKeyword.charOffset;
   }
 
@@ -658,7 +638,7 @@
       bool isFieldFormal: false,
       bool isCovariant: false,
       bool isLocalFunction: false}) {
-    return new VariableDeclarationJudgment(name, functionNestingLevel,
+    return new VariableDeclarationImpl(name, functionNestingLevel,
         type: type,
         initializer: initializer,
         isFinal: isFinal,
@@ -671,7 +651,7 @@
   VariableDeclaration createVariableDeclarationForValue(
       int fileOffset, Expression initializer,
       {DartType type = const DynamicType()}) {
-    return new VariableDeclarationJudgment.forValue(initializer)
+    return new VariableDeclarationImpl.forValue(initializer)
       ..type = type
       ..fileOffset = fileOffset ?? TreeNode.noOffset;
   }
@@ -688,7 +668,7 @@
       DartType returnType: const DynamicType(),
       AsyncMarker asyncMarker: AsyncMarker.Sync,
       AsyncMarker dartAsyncMarker}) {
-    return new FunctionNodeJudgment(body,
+    return new FunctionNode(body,
         typeParameters: typeParameters,
         positionalParameters: positionalParameters,
         namedParameters: namedParameters,
@@ -714,10 +694,19 @@
 
   MethodInvocation createFunctionInvocation(
       int fileOffset, Expression expression, Arguments arguments) {
-    return new MethodInvocationJudgment(expression, callName, arguments)
+    return new MethodInvocationImpl(expression, callName, arguments)
       ..fileOffset = fileOffset ?? TreeNode.noOffset;
   }
 
+  MethodInvocation createMethodInvocation(
+      int fileOffset, Expression expression, Name name, Arguments arguments,
+      {bool isImplicitCall: false, Member interfaceTarget}) {
+    return new MethodInvocationImpl(expression, name, arguments,
+        isImplicitCall: isImplicitCall)
+      ..fileOffset = fileOffset ?? TreeNode.noOffset
+      ..interfaceTarget = interfaceTarget;
+  }
+
   NamedExpression createNamedExpression(String name, Expression expression) {
     return new NamedExpression(name, expression);
   }
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 0f0236a..cdfc0b1 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -5,7 +5,10 @@
 part of "kernel_shadow_ast.dart";
 
 class InferenceVisitor
-    extends BodyVisitor1<ExpressionInferenceResult, DartType> {
+    implements
+        ExpressionVisitor1<ExpressionInferenceResult, DartType>,
+        StatementVisitor<void>,
+        InitializerVisitor<void> {
   final ShadowTypeInferrer inferrer;
 
   Class mapEntryClass;
@@ -24,8 +27,7 @@
 
   InferenceVisitor(this.inferrer);
 
-  @override
-  ExpressionInferenceResult defaultExpression(
+  ExpressionInferenceResult _unhandledExpression(
       Expression node, DartType typeContext) {
     unhandled("${node.runtimeType}", "InferenceVisitor", node.fileOffset,
         inferrer.helper.uri);
@@ -33,26 +35,166 @@
   }
 
   @override
-  ExpressionInferenceResult defaultStatement(Statement node, _) {
+  ExpressionInferenceResult defaultExpression(
+      Expression node, DartType typeContext) {
+    if (node is InternalExpression) {
+      switch (node.kind) {
+        case InternalExpressionKind.Cascade:
+          return visitCascade(node, typeContext);
+        case InternalExpressionKind.CompoundIndexSet:
+          return visitCompoundIndexSet(node, typeContext);
+        case InternalExpressionKind.CompoundPropertySet:
+          return visitCompoundPropertySet(node, typeContext);
+        case InternalExpressionKind.DeferredCheck:
+          return visitDeferredCheck(node, typeContext);
+        case InternalExpressionKind.IfNullIndexSet:
+          return visitIfNullIndexSet(node, typeContext);
+        case InternalExpressionKind.IfNullPropertySet:
+          return visitIfNullPropertySet(node, typeContext);
+        case InternalExpressionKind.IfNullSet:
+          return visitIfNullSet(node, typeContext);
+        case InternalExpressionKind.IndexSet:
+          return visitIndexSet(node, typeContext);
+        case InternalExpressionKind.LoadLibraryTearOff:
+          return visitLoadLibraryTearOff(node, typeContext);
+        case InternalExpressionKind.LocalPostIncDec:
+          return visitLocalPostIncDec(node, typeContext);
+        case InternalExpressionKind.NullAwareMethodInvocation:
+          return visitNullAwareMethodInvocation(node, typeContext);
+        case InternalExpressionKind.NullAwarePropertyGet:
+          return visitNullAwarePropertyGet(node, typeContext);
+        case InternalExpressionKind.NullAwarePropertySet:
+          return visitNullAwarePropertySet(node, typeContext);
+        case InternalExpressionKind.PropertyPostIncDec:
+          return visitPropertyPostIncDec(node, typeContext);
+        case InternalExpressionKind.StaticPostIncDec:
+          return visitStaticPostIncDec(node, typeContext);
+        case InternalExpressionKind.SuperPostIncDec:
+          return visitSuperPostIncDec(node, typeContext);
+      }
+    }
+    return _unhandledExpression(node, typeContext);
+  }
+
+  @override
+  ExpressionInferenceResult defaultBasicLiteral(
+      BasicLiteral node, DartType typeContext) {
+    return _unhandledExpression(node, typeContext);
+  }
+
+  @override
+  ExpressionInferenceResult visitBlockExpression(
+      BlockExpression node, DartType typeContext) {
+    return _unhandledExpression(node, typeContext);
+  }
+
+  @override
+  ExpressionInferenceResult visitConstantExpression(
+      ConstantExpression node, DartType typeContext) {
+    return _unhandledExpression(node, typeContext);
+  }
+
+  @override
+  ExpressionInferenceResult visitDirectMethodInvocation(
+      DirectMethodInvocation node, DartType typeContext) {
+    return _unhandledExpression(node, typeContext);
+  }
+
+  @override
+  ExpressionInferenceResult visitDirectPropertyGet(
+      DirectPropertyGet node, DartType typeContext) {
+    return _unhandledExpression(node, typeContext);
+  }
+
+  @override
+  ExpressionInferenceResult visitDirectPropertySet(
+      DirectPropertySet node, DartType typeContext) {
+    return _unhandledExpression(node, typeContext);
+  }
+
+  @override
+  ExpressionInferenceResult visitFileUriExpression(
+      FileUriExpression node, DartType typeContext) {
+    return _unhandledExpression(node, typeContext);
+  }
+
+  @override
+  ExpressionInferenceResult visitInstanceCreation(
+      InstanceCreation node, DartType typeContext) {
+    return _unhandledExpression(node, typeContext);
+  }
+
+  @override
+  ExpressionInferenceResult visitInstantiation(
+      Instantiation node, DartType typeContext) {
+    return _unhandledExpression(node, typeContext);
+  }
+
+  @override
+  ExpressionInferenceResult visitListConcatenation(
+      ListConcatenation node, DartType typeContext) {
+    return _unhandledExpression(node, typeContext);
+  }
+
+  @override
+  ExpressionInferenceResult visitMapConcatenation(
+      MapConcatenation node, DartType typeContext) {
+    return _unhandledExpression(node, typeContext);
+  }
+
+  @override
+  ExpressionInferenceResult visitSetConcatenation(
+      SetConcatenation node, DartType typeContext) {
+    return _unhandledExpression(node, typeContext);
+  }
+
+  void _unhandledStatement(Statement node) {
     unhandled("${node.runtimeType}", "InferenceVisitor", node.fileOffset,
         inferrer.helper.uri);
-    return const ExpressionInferenceResult(const InvalidType());
+  }
+
+  @override
+  void defaultStatement(Statement node) {
+    _unhandledStatement(node);
+  }
+
+  @override
+  void visitAssertBlock(AssertBlock node) {
+    _unhandledStatement(node);
+  }
+
+  void _unhandledInitializer(Initializer node) {
+    unhandled("${node.runtimeType}", "InferenceVisitor", node.fileOffset,
+        node.location.file);
+  }
+
+  @override
+  void defaultInitializer(Initializer node) {
+    _unhandledInitializer(node);
+  }
+
+  @override
+  void visitInvalidInitializer(Initializer node) {
+    _unhandledInitializer(node);
+  }
+
+  @override
+  void visitLocalInitializer(LocalInitializer node) {
+    _unhandledInitializer(node);
   }
 
   @override
   ExpressionInferenceResult visitInvalidExpression(
-          InvalidExpression node, DartType typeContext) =>
-      const ExpressionInferenceResult(const BottomType());
+      InvalidExpression node, DartType typeContext) {
+    return const ExpressionInferenceResult(const BottomType());
+  }
 
   @override
   ExpressionInferenceResult visitIntLiteral(
-          IntLiteral node, DartType typeContext) =>
-      new ExpressionInferenceResult(inferrer.coreTypes.intClass.rawType);
-
-  @override
-  ExpressionInferenceResult visitDoubleLiteral(
-          DoubleLiteral node, DartType typeContext) =>
-      new ExpressionInferenceResult(inferrer.coreTypes.doubleClass.rawType);
+      IntLiteral node, DartType typeContext) {
+    return new ExpressionInferenceResult(
+        inferrer.coreTypes.intRawType(inferrer.library.nonNullable));
+  }
 
   @override
   ExpressionInferenceResult visitAsExpression(
@@ -63,24 +205,23 @@
     return new ExpressionInferenceResult(node.type);
   }
 
-  void visitAssertInitializerJudgment(AssertInitializerJudgment node) {
-    inferrer.inferStatement(node.judgment);
+  @override
+  void visitAssertInitializer(AssertInitializer node) {
+    inferrer.inferStatement(node.statement);
   }
 
-  void visitAssertStatementJudgment(AssertStatementJudgment node) {
-    Expression conditionJudgment = node.conditionJudgment;
-    Expression messageJudgment = node.messageJudgment;
-    InterfaceType expectedType = inferrer.coreTypes.boolClass.rawType;
-    inferrer.inferExpression(
-        conditionJudgment, expectedType, !inferrer.isTopLevel);
+  @override
+  void visitAssertStatement(AssertStatement node) {
+    InterfaceType expectedType =
+        inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
+    DartType conditionType = inferrer
+        .inferExpression(node.condition, expectedType, !inferrer.isTopLevel)
+        .inferredType;
     inferrer.ensureAssignable(
-        expectedType,
-        getInferredType(conditionJudgment, inferrer),
-        conditionJudgment,
-        conditionJudgment.fileOffset);
-    if (messageJudgment != null) {
+        expectedType, conditionType, node.condition, node.condition.fileOffset);
+    if (node.message != null) {
       inferrer.inferExpression(
-          messageJudgment, const UnknownType(), !inferrer.isTopLevel);
+          node.message, const UnknownType(), !inferrer.isTopLevel);
     }
   }
 
@@ -90,62 +231,64 @@
     if (!inferrer.typeSchemaEnvironment.isEmptyContext(typeContext)) {
       typeContext = inferrer.wrapFutureOrType(typeContext);
     }
-    Expression operand = node.operand;
-    inferrer.inferExpression(operand, typeContext, true, isVoidAllowed: true);
-    DartType inferredType = inferrer.typeSchemaEnvironment
-        .unfutureType(getInferredType(operand, inferrer));
-    inferrer.storeInferredType(node, inferredType);
+    DartType operandType = inferrer
+        .inferExpression(node.operand, typeContext, true, isVoidAllowed: true)
+        .inferredType;
+    DartType inferredType =
+        inferrer.typeSchemaEnvironment.unfutureType(operandType);
     return new ExpressionInferenceResult(inferredType);
   }
 
-  void visitBlockJudgment(BlockJudgment node) {
-    for (Statement judgment in node.judgments) {
-      inferrer.inferStatement(judgment);
+  @override
+  void visitBlock(Block node) {
+    for (Statement statement in node.statements) {
+      inferrer.inferStatement(statement);
     }
   }
 
   @override
   ExpressionInferenceResult visitBoolLiteral(
-          BoolLiteral node, DartType typeContext) =>
-      new ExpressionInferenceResult(inferrer.coreTypes.boolClass.rawType);
+      BoolLiteral node, DartType typeContext) {
+    return new ExpressionInferenceResult(
+        inferrer.coreTypes.boolRawType(inferrer.library.nonNullable));
+  }
 
   @override
-  Null visitBreakStatement(BreakStatement node, _) {
+  void visitBreakStatement(BreakStatement node) {
     // No inference needs to be done.
   }
 
-  ExpressionInferenceResult visitCascadeJudgment(
-      CascadeJudgment node, DartType typeContext) {
+  ExpressionInferenceResult visitCascade(Cascade node, DartType typeContext) {
     ExpressionInferenceResult result =
-        inferrer.inferExpression(node.targetJudgment, typeContext, true);
-    node.inferredType = result.inferredType;
-    node.variable.type = getInferredType(node, inferrer);
-    for (Expression judgment in node.cascadeJudgments) {
+        inferrer.inferExpression(node.expression, typeContext, true);
+    node.variable.type = result.inferredType;
+    for (Expression judgment in node.cascades) {
       inferrer.inferExpression(
           judgment, const UnknownType(), !inferrer.isTopLevel,
           isVoidAllowed: true);
     }
-    return new ExpressionInferenceResult(node.inferredType);
+    Expression replacement = node.replace();
+    return new ExpressionInferenceResult(result.inferredType, replacement);
   }
 
   @override
   ExpressionInferenceResult visitConditionalExpression(
       ConditionalExpression node, DartType typeContext) {
-    Expression condition = node.condition;
-    Expression then = node.then;
-    Expression otherwise = node.otherwise;
-    InterfaceType expectedType = inferrer.coreTypes.boolClass.rawType;
-    inferrer.inferExpression(condition, expectedType, !inferrer.isTopLevel);
+    InterfaceType expectedType =
+        inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
+    DartType conditionType = inferrer
+        .inferExpression(node.condition, expectedType, !inferrer.isTopLevel)
+        .inferredType;
     inferrer.ensureAssignable(
-        expectedType,
-        getInferredType(condition, inferrer),
-        node.condition,
-        node.condition.fileOffset);
-    inferrer.inferExpression(then, typeContext, true, isVoidAllowed: true);
-    inferrer.inferExpression(otherwise, typeContext, true, isVoidAllowed: true);
+        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;
     DartType inferredType = inferrer.typeSchemaEnvironment
-        .getStandardUpperBound(getInferredType(then, inferrer),
-            getInferredType(otherwise, inferrer));
+        .getStandardUpperBound(thenType, otherwiseType);
     node.staticType = inferredType;
     return new ExpressionInferenceResult(inferredType);
   }
@@ -196,11 +339,10 @@
     DartType inferredType = inferrer.inferInvocation(
         typeContext,
         node.fileOffset,
-        node.target.function.functionType,
+        node.target.function.thisFunctionType,
         computeConstructorReturnType(node.target),
         node.arguments,
         isConst: node.isConst);
-    inferrer.storeInferredType(node, inferredType);
     if (!inferrer.isTopLevel) {
       SourceLibraryBuilder library = inferrer.library;
       if (!hasExplicitTypeArguments) {
@@ -212,46 +354,49 @@
     return new ExpressionInferenceResult(inferredType);
   }
 
-  void visitContinueSwitchJudgment(ContinueSwitchJudgment node) {
+  @override
+  void visitContinueSwitchStatement(ContinueSwitchStatement node) {
     // No inference needs to be done.
   }
 
-  ExpressionInferenceResult visitDeferredCheckJudgment(
-      DeferredCheckJudgment node, DartType typeContext) {
+  ExpressionInferenceResult visitDeferredCheck(
+      DeferredCheck node, DartType typeContext) {
     // Since the variable is not used in the body we don't need to type infer
     // it.  We can just type infer the body.
     ExpressionInferenceResult result = inferrer.inferExpression(
         node.expression, typeContext, true,
         isVoidAllowed: true);
-    node.inferredType = result.inferredType;
-    return new ExpressionInferenceResult(result.inferredType);
+    Expression replacement = node.replace();
+    return new ExpressionInferenceResult(result.inferredType, replacement);
   }
 
-  void visitDoJudgment(DoJudgment node) {
-    Expression conditionJudgment = node.conditionJudgment;
+  @override
+  void visitDoStatement(DoStatement node) {
     inferrer.inferStatement(node.body);
-    InterfaceType boolType = inferrer.coreTypes.boolClass.rawType;
-    inferrer.inferExpression(conditionJudgment, boolType, !inferrer.isTopLevel);
+    InterfaceType boolType =
+        inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
+    DartType conditionType = inferrer
+        .inferExpression(node.condition, boolType, !inferrer.isTopLevel)
+        .inferredType;
     inferrer.ensureAssignable(
-        boolType,
-        getInferredType(conditionJudgment, inferrer),
-        node.condition,
-        node.condition.fileOffset);
+        boolType, conditionType, node.condition, node.condition.fileOffset);
   }
 
-  ExpressionInferenceResult visitDoubleJudgment(
-      DoubleJudgment node, DartType typeContext) {
+  ExpressionInferenceResult visitDoubleLiteral(
+      DoubleLiteral node, DartType typeContext) {
     return new ExpressionInferenceResult(
-        node.inferredType = inferrer.coreTypes.doubleClass.rawType);
+        inferrer.coreTypes.doubleRawType(inferrer.library.nonNullable));
   }
 
-  void visitEmptyStatementJudgment(EmptyStatementJudgment node) {
+  @override
+  void visitEmptyStatement(EmptyStatement node) {
     // No inference needs to be done.
   }
 
-  void visitExpressionStatementJudgment(ExpressionStatementJudgment node) {
+  @override
+  void visitExpressionStatement(ExpressionStatement node) {
     inferrer.inferExpression(
-        node.judgment, const UnknownType(), !inferrer.isTopLevel,
+        node.expression, const UnknownType(), !inferrer.isTopLevel,
         isVoidAllowed: true);
   }
 
@@ -262,11 +407,11 @@
     DartType inferredType = inferrer.inferInvocation(
         typeContext,
         node.fileOffset,
-        node.target.function.functionType,
+        node.target.function.thisFunctionType,
         computeConstructorReturnType(node.target),
-        node.argumentJudgments,
+        node.arguments,
         isConst: node.isConst);
-    node.inferredType = inferredType;
+    node.hasBeenInferred = true;
     if (!inferrer.isTopLevel) {
       SourceLibraryBuilder library = inferrer.library;
       if (!hadExplicitTypeArguments) {
@@ -278,7 +423,8 @@
     return new ExpressionInferenceResult(inferredType);
   }
 
-  void visitShadowFieldInitializer(ShadowFieldInitializer node) {
+  @override
+  void visitFieldInitializer(FieldInitializer node) {
     ExpressionInferenceResult initializerResult =
         inferrer.inferExpression(node.value, node.field.type, true);
     DartType initializerType = initializerResult.inferredType;
@@ -292,7 +438,7 @@
     DartType elementType;
     bool typeNeeded = false;
     bool typeChecksNeeded = !inferrer.isTopLevel;
-    if (VariableDeclarationJudgment.isImplicitlyTyped(variable)) {
+    if (VariableDeclarationImpl.isImplicitlyTyped(variable)) {
       typeNeeded = true;
       elementType = const UnknownType();
     } else {
@@ -343,9 +489,14 @@
         ? inferrer.coreTypes.streamClass
         : inferrer.coreTypes.iterableClass;
     DartType context = inferrer.wrapType(elementType, iterableClass);
-    inferrer.inferExpression(iterable, context, typeNeeded);
+    ExpressionInferenceResult iterableResult =
+        inferrer.inferExpression(iterable, context, typeNeeded);
+    DartType iterableType = iterableResult.inferredType;
+    if (iterableResult.replacement != null) {
+      iterable = iterableResult.replacement;
+    }
     DartType inferredExpressionType =
-        inferrer.resolveTypeParameter(getInferredType(iterable, inferrer));
+        inferrer.resolveTypeParameter(iterableType);
     inferrer.ensureAssignable(
         inferrer.wrapType(const DynamicType(), iterableClass),
         inferredExpressionType,
@@ -374,13 +525,22 @@
     DartType syntheticWriteType;
     Expression syntheticAssignment;
     Expression rhs;
-    ExpressionStatement statement =
+    // If `true`, the synthetic statement should not be visited.
+    bool skipStatement = false;
+    ExpressionStatement syntheticStatement =
         body is Block ? body.statements.first : body;
-    SyntheticExpressionJudgment judgment = statement.expression;
-    syntheticAssignment = judgment.desugared;
+    Expression statementExpression = syntheticStatement.expression;
+    if (statementExpression is SyntheticExpressionJudgment) {
+      syntheticAssignment = statementExpression.desugared;
+    } else {
+      syntheticAssignment = statementExpression;
+    }
     if (syntheticAssignment is VariableSet) {
       syntheticWriteType = elementType = syntheticAssignment.variable.type;
       rhs = syntheticAssignment.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;
@@ -413,7 +573,17 @@
       variable.type = inferredType;
     }
 
-    inferrer.inferStatement(body);
+    if (body is Block) {
+      for (Statement statement in body.statements) {
+        if (!skipStatement || statement != syntheticStatement) {
+          inferrer.inferStatement(statement);
+        }
+      }
+    } else {
+      if (!skipStatement) {
+        inferrer.inferStatement(body);
+      }
+    }
 
     if (syntheticWriteType != null) {
       inferrer.ensureAssignable(
@@ -427,7 +597,7 @@
   }
 
   @override
-  Null visitForInStatement(ForInStatement node, _) {
+  void visitForInStatement(ForInStatement node) {
     if (node.variable.name == null) {
       handleForInWithoutVariable(node.variable, node.iterable, node.body,
           isAsync: node.isAsync);
@@ -437,14 +607,13 @@
     }
   }
 
-  void visitForJudgment(ForJudgment node) {
-    Expression conditionJudgment = node.conditionJudgment;
+  @override
+  void visitForStatement(ForStatement node) {
     for (VariableDeclaration variable in node.variables) {
       if (variable.name == null) {
-        Expression initializer = variable.initializer;
-        if (initializer != null) {
+        if (variable.initializer != null) {
           ExpressionInferenceResult result = inferrer.inferExpression(
-              initializer, const UnknownType(), true,
+              variable.initializer, const UnknownType(), true,
               isVoidAllowed: true);
           variable.type = result.inferredType;
         }
@@ -452,17 +621,16 @@
         inferrer.inferStatement(variable);
       }
     }
-    if (conditionJudgment != null) {
-      InterfaceType expectedType = inferrer.coreTypes.boolClass.rawType;
-      inferrer.inferExpression(
-          conditionJudgment, expectedType, !inferrer.isTopLevel);
-      inferrer.ensureAssignable(
-          expectedType,
-          getInferredType(conditionJudgment, inferrer),
-          node.condition,
+    if (node.condition != null) {
+      InterfaceType expectedType =
+          inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
+      DartType conditionType = inferrer
+          .inferExpression(node.condition, expectedType, !inferrer.isTopLevel)
+          .inferredType;
+      inferrer.ensureAssignable(expectedType, conditionType, node.condition,
           node.condition.fileOffset);
     }
-    for (Expression update in node.updateJudgments) {
+    for (Expression update in node.updates) {
       inferrer.inferExpression(
           update, const UnknownType(), !inferrer.isTopLevel,
           isVoidAllowed: true);
@@ -470,30 +638,27 @@
     inferrer.inferStatement(node.body);
   }
 
-  DartType visitFunctionNodeJudgment(
-      FunctionNodeJudgment node,
-      DartType typeContext,
-      DartType returnContext,
-      int returnTypeInstrumentationOffset) {
+  DartType visitFunctionNode(FunctionNode node, DartType typeContext,
+      DartType returnContext, int returnTypeInstrumentationOffset) {
     return inferrer.inferLocalFunction(
         node, typeContext, returnTypeInstrumentationOffset, returnContext);
   }
 
-  void visitFunctionDeclarationJudgment(FunctionDeclarationJudgment node) {
+  @override
+  void visitFunctionDeclaration(covariant FunctionDeclarationImpl node) {
     inferrer.inferMetadataKeepingHelper(node.variable.annotations);
     DartType returnContext =
         node._hasImplicitReturnType ? null : node.function.returnType;
-    DartType inferredType = visitFunctionNodeJudgment(
-        node.functionJudgment, null, returnContext, node.fileOffset);
+    DartType inferredType =
+        visitFunctionNode(node.function, null, returnContext, node.fileOffset);
     node.variable.type = inferredType;
   }
 
   @override
   ExpressionInferenceResult visitFunctionExpression(
       FunctionExpression node, DartType typeContext) {
-    DartType inferredType = visitFunctionNodeJudgment(
-        node.function, typeContext, null, node.fileOffset);
-    inferrer.storeInferredType(node, inferredType);
+    DartType inferredType =
+        visitFunctionNode(node.function, typeContext, null, node.fileOffset);
     return new ExpressionInferenceResult(inferredType);
   }
 
@@ -506,7 +671,7 @@
         null,
         node.fileOffset,
         substitution.substituteType(
-            node.target.function.functionType.withoutTypeParameters),
+            node.target.function.thisFunctionType.withoutTypeParameters),
         inferrer.thisType,
         node.argumentsJudgment,
         skipTypeArgumentInference: true);
@@ -514,42 +679,41 @@
 
   ExpressionInferenceResult visitIfNullJudgment(
       IfNullJudgment node, DartType typeContext) {
-    Expression leftJudgment = node.leftJudgment;
-    Expression rightJudgment = node.rightJudgment;
     // To infer `e0 ?? e1` in context K:
     // - Infer e0 in context K to get T0
-    inferrer.inferExpression(leftJudgment, typeContext, true);
-    DartType lhsType = getInferredType(leftJudgment, inferrer);
+    DartType lhsType =
+        inferrer.inferExpression(node.left, typeContext, true).inferredType;
     node.variable.type = lhsType;
     // - Let J = T0 if K is `?` else K.
     // - Infer e1 in context J to get T1
+    DartType rhsType;
     if (typeContext is UnknownType) {
-      inferrer.inferExpression(rightJudgment, lhsType, true,
-          isVoidAllowed: true);
+      rhsType = inferrer
+          .inferExpression(node.right, lhsType, true, isVoidAllowed: true)
+          .inferredType;
     } else {
-      inferrer.inferExpression(rightJudgment, typeContext, true,
-          isVoidAllowed: true);
+      rhsType = inferrer
+          .inferExpression(node.right, typeContext, true, isVoidAllowed: true)
+          .inferredType;
     }
-    DartType rhsType = getInferredType(rightJudgment, inferrer);
     // - Let T = greatest closure of K with respect to `?` if K is not `_`, else
     //   UP(t0, t1)
     // - Then the inferred type is T.
-    node.inferredType =
+    DartType inferredType =
         inferrer.typeSchemaEnvironment.getStandardUpperBound(lhsType, rhsType);
-    node.body.staticType = getInferredType(node, inferrer);
-    return new ExpressionInferenceResult(node.inferredType);
+    node.body.staticType = inferredType;
+    return new ExpressionInferenceResult(inferredType);
   }
 
-  void visitIfJudgment(IfJudgment node) {
-    Expression conditionJudgment = node.conditionJudgment;
-    InterfaceType expectedType = inferrer.coreTypes.boolClass.rawType;
-    inferrer.inferExpression(
-        conditionJudgment, expectedType, !inferrer.isTopLevel);
+  @override
+  void visitIfStatement(IfStatement node) {
+    InterfaceType expectedType =
+        inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
+    DartType conditionType = inferrer
+        .inferExpression(node.condition, expectedType, !inferrer.isTopLevel)
+        .inferredType;
     inferrer.ensureAssignable(
-        expectedType,
-        getInferredType(conditionJudgment, inferrer),
-        node.condition,
-        node.condition.fileOffset);
+        expectedType, conditionType, node.condition, node.condition.fileOffset);
     inferrer.inferStatement(node.then);
     if (node.otherwise != null) {
       inferrer.inferStatement(node.otherwise);
@@ -565,7 +729,6 @@
     inferrer.inferExpression(
         node.rhs, const UnknownType(), !inferrer.isTopLevel);
     node._replaceWithDesugared();
-    node.inferredType = const DynamicType();
     return const ExpressionInferenceResult(const DynamicType());
   }
 
@@ -579,7 +742,7 @@
     // when doing compound assignment?
     DartType indexContext = const UnknownType();
     DartType expectedIndexTypeForWrite =
-        inferrer.getIndexSetKeyType(writeTarget, receiverType);
+        inferrer.getIndexKeyType(writeTarget, receiverType);
     DartType writeContext =
         inferrer.getIndexSetValueType(writeTarget, receiverType);
     ExpressionInferenceResult indexResult =
@@ -618,8 +781,8 @@
       MethodInvocation desugaredInvocation =
           read is MethodInvocation ? read : null;
       MethodContravarianceCheckKind checkKind =
-          inferrer.preCheckInvocationContravariance(node.receiver, receiverType,
-              readMember, desugaredInvocation, read.arguments, read);
+          inferrer.preCheckInvocationContravariance(receiverType, readMember,
+              isThisReceiver: node.receiver is ThisExpression);
       Expression replacedRead = inferrer.handleInvocationContravariance(
           checkKind,
           desugaredInvocation,
@@ -643,19 +806,21 @@
       if (doubleValue != null) {
         node.parent.replaceChild(
             node, new DoubleLiteral(doubleValue)..fileOffset = node.fileOffset);
-        node.inferredType = inferrer.coreTypes.doubleClass.rawType;
-        return new ExpressionInferenceResult(node.inferredType);
+        DartType inferredType =
+            inferrer.coreTypes.doubleRawType(inferrer.library.nonNullable);
+        return new ExpressionInferenceResult(inferredType);
       }
     }
     Expression error = checkWebIntLiteralsErrorIfUnexact(
         inferrer, node.value, node.literal, node.fileOffset);
+
     if (error != null) {
       node.parent.replaceChild(node, error);
-      node.inferredType = const BottomType();
       return const ExpressionInferenceResult(const BottomType());
     }
-    node.inferredType = inferrer.coreTypes.intClass.rawType;
-    return new ExpressionInferenceResult(node.inferredType);
+    DartType inferredType =
+        inferrer.coreTypes.intRawType(inferrer.library.nonNullable);
+    return new ExpressionInferenceResult(inferredType);
   }
 
   ExpressionInferenceResult visitShadowLargeIntLiteral(
@@ -665,8 +830,9 @@
       if (doubleValue != null) {
         node.parent.replaceChild(
             node, new DoubleLiteral(doubleValue)..fileOffset = node.fileOffset);
-        node.inferredType = inferrer.coreTypes.doubleClass.rawType;
-        return new ExpressionInferenceResult(node.inferredType);
+        DartType inferredType =
+            inferrer.coreTypes.doubleRawType(inferrer.library.nonNullable);
+        return new ExpressionInferenceResult(inferredType);
       }
     }
 
@@ -678,20 +844,19 @@
               node.fileOffset,
               node.literal.length));
       node.parent.replaceChild(node, replacement);
-      node.inferredType = const BottomType();
       return const ExpressionInferenceResult(const BottomType());
     }
     Expression error = checkWebIntLiteralsErrorIfUnexact(
         inferrer, intValue, node.literal, node.fileOffset);
     if (error != null) {
       node.parent.replaceChild(node, error);
-      node.inferredType = const BottomType();
       return const ExpressionInferenceResult(const BottomType());
     }
     node.parent.replaceChild(
         node, new IntLiteral(intValue)..fileOffset = node.fileOffset);
-    node.inferredType = inferrer.coreTypes.intClass.rawType;
-    return new ExpressionInferenceResult(node.inferredType);
+    DartType inferredType =
+        inferrer.coreTypes.intRawType(inferrer.library.nonNullable);
+    return new ExpressionInferenceResult(inferredType);
   }
 
   void visitShadowInvalidInitializer(ShadowInvalidInitializer node) {
@@ -708,11 +873,12 @@
       IsExpression node, DartType typeContext) {
     inferrer.inferExpression(
         node.operand, const UnknownType(), !inferrer.isTopLevel);
-    return new ExpressionInferenceResult(inferrer.coreTypes.boolClass.rawType);
+    return new ExpressionInferenceResult(
+        inferrer.coreTypes.boolRawType(inferrer.library.nonNullable));
   }
 
   @override
-  Null visitLabeledStatement(LabeledStatement node, _) {
+  void visitLabeledStatement(LabeledStatement node) {
     inferrer.inferStatement(node.body);
   }
 
@@ -735,6 +901,7 @@
       TreeNode parent,
       DartType inferredTypeArgument,
       Map<TreeNode, DartType> inferredSpreadTypes,
+      Map<Expression, DartType> inferredConditionTypes,
       bool inferenceNeeded,
       bool typeChecksNeeded) {
     if (element is SpreadElement) {
@@ -785,7 +952,8 @@
           getSpreadElementType(spreadType, element.isNullAware) ??
               const DynamicType();
     } else if (element is IfElement) {
-      DartType boolType = inferrer.coreTypes.boolClass.rawType;
+      DartType boolType =
+          inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
       ExpressionInferenceResult conditionResult = inferrer.inferExpression(
           element.condition, boolType, typeChecksNeeded,
           isVoidAllowed: false);
@@ -797,6 +965,7 @@
           element,
           inferredTypeArgument,
           inferredSpreadTypes,
+          inferredConditionTypes,
           inferenceNeeded,
           typeChecksNeeded);
       DartType otherwiseType;
@@ -806,6 +975,7 @@
             element,
             inferredTypeArgument,
             inferredSpreadTypes,
+            inferredConditionTypes,
             inferenceNeeded,
             typeChecksNeeded);
       }
@@ -828,19 +998,27 @@
         }
       }
       if (element.condition != null) {
-        inferrer.inferExpression(
-            element.condition,
-            inferrer.coreTypes.boolClass.rawType,
-            inferenceNeeded || typeChecksNeeded,
-            isVoidAllowed: false);
+        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(),
             inferenceNeeded || typeChecksNeeded,
             isVoidAllowed: true);
       }
-      return inferElement(element.body, element, inferredTypeArgument,
-          inferredSpreadTypes, inferenceNeeded, typeChecksNeeded);
+      return inferElement(
+          element.body,
+          element,
+          inferredTypeArgument,
+          inferredSpreadTypes,
+          inferredConditionTypes,
+          inferenceNeeded,
+          typeChecksNeeded);
     } else if (element is ForInElement) {
       if (element.variable.name == null) {
         handleForInWithoutVariable(
@@ -856,12 +1034,21 @@
             inferenceNeeded || typeChecksNeeded,
             isVoidAllowed: true);
       }
-      return inferElement(element.body, element, inferredTypeArgument,
-          inferredSpreadTypes, inferenceNeeded, typeChecksNeeded);
+      return inferElement(
+          element.body,
+          element,
+          inferredTypeArgument,
+          inferredSpreadTypes,
+          inferredConditionTypes,
+          inferenceNeeded,
+          typeChecksNeeded);
     } else {
       ExpressionInferenceResult result = inferrer.inferExpression(
           element, inferredTypeArgument, inferenceNeeded || typeChecksNeeded,
           isVoidAllowed: true);
+      if (result.replacement != null) {
+        element = result.replacement;
+      }
       DartType inferredType = result.inferredType;
       if (inferredTypeArgument is! UnknownType) {
         inferrer.ensureAssignable(
@@ -872,35 +1059,51 @@
     }
   }
 
-  void checkElement(Expression item, Expression parent, DartType typeArgument,
-      Map<TreeNode, DartType> inferredSpreadTypes) {
+  void checkElement(
+      Expression item,
+      Expression parent,
+      DartType typeArgument,
+      Map<TreeNode, DartType> inferredSpreadTypes,
+      Map<Expression, DartType> inferredConditionTypes) {
     if (item is SpreadElement) {
       DartType spreadType = inferredSpreadTypes[item.expression];
       if (spreadType is DynamicType) {
-        inferrer.ensureAssignable(inferrer.coreTypes.iterableClass.rawType,
-            spreadType, item.expression, item.expression.fileOffset);
+        inferrer.ensureAssignable(
+            inferrer.coreTypes.iterableRawType(
+                inferrer.library.nullableIfTrue(item.isNullAware)),
+            spreadType,
+            item.expression,
+            item.expression.fileOffset);
       }
     } else if (item is IfElement) {
-      checkElement(item.then, item, typeArgument, inferredSpreadTypes);
+      checkElement(item.then, item, typeArgument, inferredSpreadTypes,
+          inferredConditionTypes);
       if (item.otherwise != null) {
-        checkElement(item.otherwise, item, typeArgument, inferredSpreadTypes);
+        checkElement(item.otherwise, item, typeArgument, inferredSpreadTypes,
+            inferredConditionTypes);
       }
     } else if (item is ForElement) {
       if (item.condition != null) {
-        DartType conditionType = getInferredType(item.condition, inferrer);
-        inferrer.ensureAssignable(inferrer.coreTypes.boolClass.rawType,
-            conditionType, item.condition, item.condition.fileOffset);
+        DartType conditionType = inferredConditionTypes[item.condition];
+        inferrer.ensureAssignable(
+            inferrer.coreTypes.boolRawType(inferrer.library.nonNullable),
+            conditionType,
+            item.condition,
+            item.condition.fileOffset);
       }
-      checkElement(item.body, item, typeArgument, inferredSpreadTypes);
+      checkElement(item.body, item, typeArgument, inferredSpreadTypes,
+          inferredConditionTypes);
     } else if (item is ForInElement) {
-      checkElement(item.body, item, typeArgument, inferredSpreadTypes);
+      checkElement(item.body, item, typeArgument, inferredSpreadTypes,
+          inferredConditionTypes);
     } else {
       // Do nothing.  Assignability checks are done during type inference.
     }
   }
 
-  ExpressionInferenceResult visitListLiteralJudgment(
-      ListLiteralJudgment node, DartType typeContext) {
+  @override
+  ExpressionInferenceResult visitListLiteral(
+      ListLiteral node, DartType typeContext) {
     Class listClass = inferrer.coreTypes.listClass;
     InterfaceType listType = listClass.thisType;
     List<DartType> inferredTypes;
@@ -910,10 +1113,12 @@
     bool inferenceNeeded = node.typeArgument is ImplicitTypeArgument;
     bool typeChecksNeeded = !inferrer.isTopLevel;
     Map<TreeNode, DartType> inferredSpreadTypes;
+    Map<Expression, DartType> inferredConditionTypes;
     if (inferenceNeeded || typeChecksNeeded) {
       formalTypes = [];
       actualTypes = [];
       inferredSpreadTypes = new Map<TreeNode, DartType>.identity();
+      inferredConditionTypes = new Map<Expression, DartType>.identity();
     }
     if (inferenceNeeded) {
       inferredTypes = [const UnknownType()];
@@ -931,6 +1136,7 @@
             node,
             inferredTypeArgument,
             inferredSpreadTypes,
+            inferredConditionTypes,
             inferenceNeeded,
             typeChecksNeeded);
         actualTypes.add(type);
@@ -957,11 +1163,12 @@
     }
     if (typeChecksNeeded) {
       for (int i = 0; i < node.expressions.length; i++) {
-        checkElement(
-            node.expressions[i], node, node.typeArgument, inferredSpreadTypes);
+        checkElement(node.expressions[i], node, node.typeArgument,
+            inferredSpreadTypes, inferredConditionTypes);
       }
     }
-    node.inferredType = new InterfaceType(listClass, [inferredTypeArgument]);
+    DartType inferredType =
+        new InterfaceType(listClass, [inferredTypeArgument]);
     if (!inferrer.isTopLevel) {
       SourceLibraryBuilder library = inferrer.library;
       if (inferenceNeeded) {
@@ -971,21 +1178,24 @@
       }
     }
 
-    return new ExpressionInferenceResult(node.inferredType);
+    return new ExpressionInferenceResult(inferredType);
   }
 
   @override
   ExpressionInferenceResult visitLogicalExpression(
       LogicalExpression node, DartType typeContext) {
-    InterfaceType boolType = inferrer.coreTypes.boolClass.rawType;
-    Expression left = node.left;
-    Expression right = node.right;
-    inferrer.inferExpression(left, boolType, !inferrer.isTopLevel);
-    inferrer.inferExpression(right, boolType, !inferrer.isTopLevel);
-    inferrer.ensureAssignable(boolType, getInferredType(left, inferrer),
-        node.left, node.left.fileOffset);
-    inferrer.ensureAssignable(boolType, getInferredType(right, inferrer),
-        node.right, node.right.fileOffset);
+    InterfaceType boolType =
+        inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
+    DartType leftType = inferrer
+        .inferExpression(node.left, boolType, !inferrer.isTopLevel)
+        .inferredType;
+    DartType rightType = inferrer
+        .inferExpression(node.right, boolType, !inferrer.isTopLevel)
+        .inferredType;
+    inferrer.ensureAssignable(
+        boolType, leftType, node.left, node.left.fileOffset);
+    inferrer.ensureAssignable(
+        boolType, rightType, node.right, node.right.fileOffset);
     return new ExpressionInferenceResult(boolType);
   }
 
@@ -1025,6 +1235,7 @@
       List<DartType> actualTypes,
       List<DartType> actualTypesForSet,
       Map<TreeNode, DartType> inferredSpreadTypes,
+      Map<Expression, DartType> inferredConditionTypes,
       bool inferenceNeeded,
       bool typeChecksNeeded) {
     if (entry is SpreadMapEntry) {
@@ -1118,10 +1329,10 @@
       entry.entryType = new InterfaceType(
           mapEntryClass, <DartType>[actualKeyType, actualValueType]);
 
-      bool isMap = inferrer.typeSchemaEnvironment
-          .isSubtypeOf(spreadType, inferrer.coreTypes.mapClass.rawType);
-      bool isIterable = inferrer.typeSchemaEnvironment
-          .isSubtypeOf(spreadType, inferrer.coreTypes.iterableClass.rawType);
+      bool isMap = inferrer.typeSchemaEnvironment.isSubtypeOf(
+          spreadType, inferrer.coreTypes.mapRawType(inferrer.library.nullable));
+      bool isIterable = inferrer.typeSchemaEnvironment.isSubtypeOf(spreadType,
+          inferrer.coreTypes.iterableRawType(inferrer.library.nullable));
       if (isMap && !isIterable) {
         mapSpreadOffset = entry.fileOffset;
       }
@@ -1131,7 +1342,8 @@
 
       return;
     } else if (entry is IfMapEntry) {
-      DartType boolType = inferrer.coreTypes.boolClass.rawType;
+      DartType boolType =
+          inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
       ExpressionInferenceResult conditionResult = inferrer.inferExpression(
           entry.condition, boolType, typeChecksNeeded,
           isVoidAllowed: false);
@@ -1150,6 +1362,7 @@
           actualTypes,
           actualTypesForSet,
           inferredSpreadTypes,
+          inferredConditionTypes,
           inferenceNeeded,
           typeChecksNeeded);
       if (entry.otherwise != null) {
@@ -1167,6 +1380,7 @@
             actualTypes,
             actualTypesForSet,
             inferredSpreadTypes,
+            inferredConditionTypes,
             inferenceNeeded,
             typeChecksNeeded);
         int length = actualTypes.length;
@@ -1196,11 +1410,13 @@
         }
       }
       if (entry.condition != null) {
-        inferrer.inferExpression(
-            entry.condition,
-            inferrer.coreTypes.boolClass.rawType,
-            inferenceNeeded || typeChecksNeeded,
-            isVoidAllowed: false);
+        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(),
@@ -1217,6 +1433,7 @@
           actualTypes,
           actualTypesForSet,
           inferredSpreadTypes,
+          inferredConditionTypes,
           inferenceNeeded,
           typeChecksNeeded);
     } else if (entry is ForInMapEntry) {
@@ -1244,6 +1461,7 @@
           actualTypes,
           actualTypesForSet,
           inferredSpreadTypes,
+          inferredConditionTypes,
           inferenceNeeded,
           typeChecksNeeded);
     } else {
@@ -1277,7 +1495,8 @@
       Expression cachedValue,
       DartType keyType,
       DartType valueType,
-      Map<TreeNode, DartType> inferredSpreadTypes) {
+      Map<TreeNode, DartType> inferredSpreadTypes,
+      Map<Expression, DartType> inferredConditionTypes) {
     // It's disambiguated as a map literal.
     if (iterableSpreadOffset != null) {
       parent.replaceChild(
@@ -1294,34 +1513,42 @@
     if (entry is SpreadMapEntry) {
       DartType spreadType = inferredSpreadTypes[entry.expression];
       if (spreadType is DynamicType) {
-        inferrer.ensureAssignable(inferrer.coreTypes.mapClass.rawType,
-            spreadType, entry.expression, entry.expression.fileOffset);
+        inferrer.ensureAssignable(
+            inferrer.coreTypes
+                .mapRawType(inferrer.library.nullableIfTrue(entry.isNullAware)),
+            spreadType,
+            entry.expression,
+            entry.expression.fileOffset);
       }
     } else if (entry is IfMapEntry) {
       checkMapEntry(entry.then, entry, cachedKey, cachedValue, keyType,
-          valueType, inferredSpreadTypes);
+          valueType, inferredSpreadTypes, inferredConditionTypes);
       if (entry.otherwise != null) {
         checkMapEntry(entry.otherwise, entry, cachedKey, cachedValue, keyType,
-            valueType, inferredSpreadTypes);
+            valueType, inferredSpreadTypes, inferredConditionTypes);
       }
     } else if (entry is ForMapEntry) {
       if (entry.condition != null) {
-        DartType conditionType = getInferredType(entry.condition, inferrer);
-        inferrer.ensureAssignable(inferrer.coreTypes.boolClass.rawType,
-            conditionType, entry.condition, entry.condition.fileOffset);
+        DartType conditionType = inferredConditionTypes[entry.condition];
+        inferrer.ensureAssignable(
+            inferrer.coreTypes.boolRawType(inferrer.library.nonNullable),
+            conditionType,
+            entry.condition,
+            entry.condition.fileOffset);
       }
       checkMapEntry(entry.body, entry, cachedKey, cachedValue, keyType,
-          valueType, inferredSpreadTypes);
+          valueType, inferredSpreadTypes, inferredConditionTypes);
     } else if (entry is ForInMapEntry) {
       checkMapEntry(entry.body, entry, cachedKey, cachedValue, keyType,
-          valueType, inferredSpreadTypes);
+          valueType, inferredSpreadTypes, inferredConditionTypes);
     } else {
       // Do nothing.  Assignability checks are done during type inference.
     }
   }
 
-  ExpressionInferenceResult visitMapLiteralJudgment(
-      MapLiteralJudgment node, DartType typeContext) {
+  @override
+  ExpressionInferenceResult visitMapLiteral(
+      MapLiteral node, DartType typeContext) {
     Class mapClass = inferrer.coreTypes.mapClass;
     InterfaceType mapType = mapClass.thisType;
     List<DartType> inferredTypes;
@@ -1350,23 +1577,26 @@
             typeContextIsIterable &&
             !typeContextIsMap) {
           // Set literal
-          SetLiteralJudgment setLiteral = new SetLiteralJudgment([],
+          SetLiteral setLiteral = new SetLiteral([],
               typeArgument: const ImplicitTypeArgument(), isConst: node.isConst)
             ..fileOffset = node.fileOffset;
           node.parent.replaceChild(node, setLiteral);
-          visitSetLiteralJudgment(setLiteral, typeContext);
-          node.inferredType = setLiteral.inferredType;
-          return new ExpressionInferenceResult(node.inferredType);
+          ExpressionInferenceResult setLiteralResult =
+              visitSetLiteral(setLiteral, typeContext);
+          DartType inferredType = setLiteralResult.inferredType;
+          return new ExpressionInferenceResult(inferredType);
         }
       }
     }
     bool typeChecksNeeded = !inferrer.isTopLevel;
     Map<TreeNode, DartType> inferredSpreadTypes;
+    Map<Expression, DartType> inferredConditionTypes;
     if (inferenceNeeded || typeChecksNeeded) {
       formalTypes = [];
       actualTypes = [];
       actualTypesForSet = [];
       inferredSpreadTypes = new Map<TreeNode, DartType>.identity();
+      inferredConditionTypes = new Map<Expression, DartType>.identity();
     }
     if (inferenceNeeded) {
       inferredTypes = [const UnknownType(), const UnknownType()];
@@ -1415,6 +1645,7 @@
             actualTypes,
             actualTypesForSet,
             inferredSpreadTypes,
+            inferredConditionTypes,
             inferenceNeeded,
             typeChecksNeeded);
         if (inferenceNeeded) {
@@ -1461,20 +1692,24 @@
             'typeArgs',
             new InstrumentationValueForTypeArgs([inferredTypeArgument]));
 
-        SetLiteralJudgment setLiteral = new SetLiteralJudgment(setElements,
+        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(setLiteral.expressions[i], setLiteral,
-                setLiteral.typeArgument, inferredSpreadTypes);
+            checkElement(
+                setLiteral.expressions[i],
+                setLiteral,
+                setLiteral.typeArgument,
+                inferredSpreadTypes,
+                inferredConditionTypes);
           }
         }
 
-        node.inferredType = setLiteral.inferredType =
+        DartType inferredType =
             new InterfaceType(inferrer.coreTypes.setClass, inferredTypesForSet);
-        return new ExpressionInferenceResult(node.inferredType);
+        return new ExpressionInferenceResult(inferredType);
       }
       if (canBeSet && canBeMap && node.entries.isNotEmpty) {
         node.parent.replaceChild(
@@ -1482,7 +1717,6 @@
             inferrer.helper.desugarSyntheticExpression(inferrer.helper
                 .buildProblem(messageCantDisambiguateNotEnoughInformation,
                     node.fileOffset, 1)));
-        node.inferredType = const BottomType();
         return const ExpressionInferenceResult(const BottomType());
       }
       if (!canBeSet && !canBeMap) {
@@ -1493,7 +1727,6 @@
                   .buildProblem(messageCantDisambiguateAmbiguousInformation,
                       node.fileOffset, 1)));
         }
-        node.inferredType = const BottomType();
         return const ExpressionInferenceResult(const BottomType());
       }
       inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
@@ -1516,11 +1749,18 @@
     }
     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);
+        checkMapEntry(
+            node.entries[i],
+            node,
+            cachedKeys[i],
+            cachedValues[i],
+            node.keyType,
+            node.valueType,
+            inferredSpreadTypes,
+            inferredConditionTypes);
       }
     }
-    node.inferredType =
+    DartType inferredType =
         new InterfaceType(mapClass, [inferredKeyType, inferredValueType]);
     if (!inferrer.isTopLevel) {
       SourceLibraryBuilder library = inferrer.library;
@@ -1532,11 +1772,12 @@
             inferred: true);
       }
     }
-    return new ExpressionInferenceResult(node.inferredType);
+    return new ExpressionInferenceResult(inferredType);
   }
 
-  ExpressionInferenceResult visitMethodInvocationJudgment(
-      MethodInvocationJudgment node, DartType typeContext) {
+  @override
+  ExpressionInferenceResult visitMethodInvocation(
+      covariant MethodInvocationImpl node, DartType typeContext) {
     if (node.name.name == 'unary-' &&
         node.arguments.types.isEmpty &&
         node.arguments.positional.isEmpty &&
@@ -1557,15 +1798,15 @@
           if (doubleValue != null) {
             node.parent.replaceChild(node,
                 new DoubleLiteral(doubleValue)..fileOffset = node.fileOffset);
-            node.inferredType = inferrer.coreTypes.doubleClass.rawType;
-            return new ExpressionInferenceResult(node.inferredType);
+            DartType inferredType =
+                inferrer.coreTypes.doubleRawType(inferrer.library.nonNullable);
+            return new ExpressionInferenceResult(inferredType);
           }
         }
         Expression error = checkWebIntLiteralsErrorIfUnexact(
             inferrer, receiver.value, receiver.literal, receiver.fileOffset);
         if (error != null) {
           node.parent.replaceChild(node, error);
-          node.inferredType = const BottomType();
           return const ExpressionInferenceResult(const BottomType());
         }
       } else if (node.receiver is ShadowLargeIntLiteral) {
@@ -1576,8 +1817,9 @@
             if (doubleValue != null) {
               node.parent.replaceChild(node,
                   new DoubleLiteral(doubleValue)..fileOffset = node.fileOffset);
-              node.inferredType = inferrer.coreTypes.doubleClass.rawType;
-              return new ExpressionInferenceResult(node.inferredType);
+              DartType inferredType = inferrer.coreTypes
+                  .doubleRawType(inferrer.library.nonNullable);
+              return new ExpressionInferenceResult(inferredType);
             }
           }
           int intValue = receiver.asInt64(negated: true);
@@ -1589,7 +1831,6 @@
                     receiver.fileOffset,
                     receiver.literal.length));
             node.parent.replaceChild(node, error);
-            node.inferredType = const BottomType();
             return const ExpressionInferenceResult(const BottomType());
           }
           if (intValue != null) {
@@ -1597,7 +1838,6 @@
                 inferrer, intValue, receiver.literal, receiver.fileOffset);
             if (error != null) {
               node.parent.replaceChild(node, error);
-              node.inferredType = const BottomType();
               return const ExpressionInferenceResult(const BottomType());
             }
             node.receiver = new IntLiteral(-intValue)
@@ -1607,57 +1847,786 @@
         }
       }
     }
-    ExpressionInferenceResult result = inferrer.inferMethodInvocation(
-        node, node.receiver, node.fileOffset, node._isImplicitCall, typeContext,
-        desugaredInvocation: node);
-    node.inferredType = result.inferredType;
+    ExpressionInferenceResult result =
+        inferrer.inferMethodInvocation(node, typeContext);
     return new ExpressionInferenceResult(
         result.inferredType, result.replacement);
   }
 
   ExpressionInferenceResult visitNamedFunctionExpressionJudgment(
       NamedFunctionExpressionJudgment node, DartType typeContext) {
-    Expression initializer = node.variableJudgment.initializer;
-    inferrer.inferExpression(initializer, typeContext, true);
-    node.inferredType = getInferredType(initializer, inferrer);
-    node.variable.type = node.inferredType;
-    return new ExpressionInferenceResult(node.inferredType);
+    DartType inferredType = inferrer
+        .inferExpression(node.variable.initializer, typeContext, true)
+        .inferredType;
+    node.variable.type = inferredType;
+    return new ExpressionInferenceResult(inferredType);
   }
 
   @override
   ExpressionInferenceResult visitNot(Not node, DartType typeContext) {
-    Expression operand = node.operand;
-    InterfaceType boolType = inferrer.coreTypes.boolClass.rawType;
-    inferrer.inferExpression(operand, boolType, !inferrer.isTopLevel);
-    inferrer.ensureAssignable(boolType, getInferredType(operand, inferrer),
-        node.operand, node.fileOffset);
+    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 visitNullAwareMethodInvocationJudgment(
-      NullAwareMethodInvocationJudgment node, DartType typeContext) {
-    ExpressionInferenceResult result = inferrer.inferMethodInvocation(
-        node, node.variable.initializer, node.fileOffset, false, typeContext,
-        receiverVariable: node.variable,
-        desugaredInvocation: node._desugaredInvocation);
-    node.inferredType = result.inferredType;
-    node.body.staticType = node.inferredType;
-    return new ExpressionInferenceResult(result.inferredType);
+  ExpressionInferenceResult visitNullAwareMethodInvocation(
+      NullAwareMethodInvocation node, DartType typeContext) {
+    inferrer.inferStatement(node.variable);
+    ExpressionInferenceResult readResult = inferrer.inferExpression(
+        node.invocation, typeContext, true,
+        isVoidAllowed: true);
+    Member equalsMember = inferrer
+        .findInterfaceMember(
+            node.variable.type, new Name('=='), 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);
   }
 
-  ExpressionInferenceResult visitNullAwarePropertyGetJudgment(
-      NullAwarePropertyGetJudgment node, DartType typeContext) {
-    ExpressionInferenceResult result = inferrer.inferPropertyGet(
-        node, node.receiverJudgment, node.fileOffset, typeContext,
-        receiverVariable: node.variable, desugaredGet: node._desugaredGet);
-    node.body.staticType = result.inferredType;
-    return new ExpressionInferenceResult(result.inferredType);
+  ExpressionInferenceResult visitNullAwarePropertyGet(
+      NullAwarePropertyGet node, DartType typeContext) {
+    inferrer.inferStatement(node.variable);
+    ExpressionInferenceResult readResult =
+        inferrer.inferExpression(node.read, const UnknownType(), true);
+    Member equalsMember = inferrer
+        .findInterfaceMember(
+            node.variable.type, new Name('=='), 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);
+  }
+
+  ExpressionInferenceResult visitNullAwarePropertySet(
+      NullAwarePropertySet node, DartType typeContext) {
+    inferrer.inferStatement(node.variable);
+    ExpressionInferenceResult writeResult =
+        inferrer.inferExpression(node.write, typeContext, true);
+    Member equalsMember = inferrer
+        .findInterfaceMember(
+            node.variable.type, new Name('=='), 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);
+  }
+
+  ExpressionInferenceResult visitStaticPostIncDec(
+      StaticPostIncDec node, DartType typeContext) {
+    inferrer.inferStatement(node.read);
+    inferrer.inferStatement(node.write);
+    DartType inferredType = node.read.type;
+    Expression replacement = node.replace();
+    return new ExpressionInferenceResult(inferredType, replacement);
+  }
+
+  ExpressionInferenceResult visitSuperPostIncDec(
+      SuperPostIncDec node, DartType typeContext) {
+    inferrer.inferStatement(node.read);
+    inferrer.inferStatement(node.write);
+    DartType inferredType = node.read.type;
+    Expression replacement = node.replace();
+    return new ExpressionInferenceResult(inferredType, replacement);
+  }
+
+  ExpressionInferenceResult visitLocalPostIncDec(
+      LocalPostIncDec node, DartType typeContext) {
+    inferrer.inferStatement(node.read);
+    inferrer.inferStatement(node.write);
+    DartType inferredType = node.read.type;
+    Expression replacement = node.replace();
+    return new ExpressionInferenceResult(inferredType, replacement);
+  }
+
+  ExpressionInferenceResult visitPropertyPostIncDec(
+      PropertyPostIncDec node, DartType typeContext) {
+    inferrer.inferStatement(node.variable);
+    inferrer.inferStatement(node.read);
+    inferrer.inferStatement(node.write);
+    DartType inferredType = node.read.type;
+    Expression replacement = node.replace();
+    return new ExpressionInferenceResult(inferredType, replacement);
+  }
+
+  ExpressionInferenceResult visitCompoundPropertySet(
+      CompoundPropertySet node, DartType typeContext) {
+    inferrer.inferStatement(node.variable);
+    ExpressionInferenceResult writeResult =
+        inferrer.inferExpression(node.write, typeContext, true);
+    Expression replacement = node.replace();
+    return new ExpressionInferenceResult(writeResult.inferredType, replacement);
+  }
+
+  ExpressionInferenceResult visitIfNullPropertySet(
+      IfNullPropertySet node, DartType typeContext) {
+    inferrer.inferStatement(node.variable);
+    ExpressionInferenceResult readResult =
+        inferrer.inferExpression(node.read, const UnknownType(), true);
+    ExpressionInferenceResult writeResult =
+        inferrer.inferExpression(node.write, typeContext, true);
+    Member equalsMember = inferrer
+        .findInterfaceMember(
+            readResult.inferredType, new Name('=='), node.fileOffset)
+        .member;
+
+    DartType inferredType = inferrer.typeSchemaEnvironment
+        .getStandardUpperBound(
+            readResult.inferredType, writeResult.inferredType);
+
+    Expression replacement;
+    if (node.forEffect) {
+      // Encode `o.a ??= b` as:
+      //
+      //     let v1 = o in v1.a == null ? v1.a = b : null
+      //
+      MethodInvocation equalsNull =
+          createEqualsNull(node.fileOffset, node.read, equalsMember);
+      ConditionalExpression conditional = new ConditionalExpression(
+          equalsNull,
+          node.write,
+          new NullLiteral()..fileOffset = node.fileOffset,
+          inferredType)
+        ..fileOffset = node.fileOffset;
+      node.replaceWith(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);
+      MethodInvocation equalsNull = createEqualsNull(
+          node.fileOffset, createVariableGet(readVariable), equalsMember);
+      ConditionalExpression conditional = new ConditionalExpression(
+          equalsNull, node.write, createVariableGet(readVariable), inferredType)
+        ..fileOffset = node.fileOffset;
+      node.replaceWith(replacement =
+          new Let(node.variable, createLet(readVariable, conditional))
+            ..fileOffset = node.fileOffset);
+    }
+
+    return new ExpressionInferenceResult(inferredType, replacement);
+  }
+
+  ExpressionInferenceResult visitIfNullSet(
+      IfNullSet node, DartType typeContext) {
+    ExpressionInferenceResult readResult =
+        inferrer.inferExpression(node.read, const UnknownType(), true);
+    ExpressionInferenceResult writeResult =
+        inferrer.inferExpression(node.write, typeContext, true);
+    Member equalsMember = inferrer
+        .findInterfaceMember(
+            readResult.inferredType, new Name('=='), node.fileOffset)
+        .member;
+
+    DartType inferredType = inferrer.typeSchemaEnvironment
+        .getStandardUpperBound(
+            readResult.inferredType, writeResult.inferredType);
+
+    Expression replacement;
+    if (node.forEffect) {
+      // Encode `a ??= b` as:
+      //
+      //     a == null ? a = b : null
+      //
+      MethodInvocation equalsNull =
+          createEqualsNull(node.fileOffset, node.read, equalsMember);
+      node.replaceWith(replacement = new ConditionalExpression(
+          equalsNull,
+          node.write,
+          new NullLiteral()..fileOffset = node.fileOffset,
+          inferredType)
+        ..fileOffset = node.fileOffset);
+    } else {
+      // Encode `a ??= b` as:
+      //
+      //      let v1 = a in v1 == null ? a = b : v1
+      //
+      VariableDeclaration readVariable =
+          createVariable(node.read, readResult.inferredType);
+      MethodInvocation equalsNull = createEqualsNull(
+          node.fileOffset, createVariableGet(readVariable), equalsMember);
+      ConditionalExpression conditional = new ConditionalExpression(
+          equalsNull, node.write, createVariableGet(readVariable), inferredType)
+        ..fileOffset = node.fileOffset;
+      node.replaceWith(replacement = new Let(readVariable, conditional)
+        ..fileOffset = node.fileOffset);
+    }
+    return new ExpressionInferenceResult(inferredType, replacement);
+  }
+
+  ExpressionInferenceResult visitIndexSet(IndexSet node, DartType typeContext) {
+    ExpressionInferenceResult receiverResult = inferrer.inferExpression(
+        node.receiver, const UnknownType(), true,
+        isVoidAllowed: true);
+    DartType receiverType = receiverResult.inferredType;
+    VariableDeclaration receiverVariable =
+        createVariable(node.receiver, receiverType);
+
+    ObjectAccessTarget indexSetTarget = inferrer.findInterfaceMember(
+        receiverType, new Name('[]='), node.fileOffset,
+        includeExtensionMethods: true);
+
+    DartType indexType = inferrer.getIndexKeyType(indexSetTarget, receiverType);
+    DartType valueType =
+        inferrer.getIndexSetValueType(indexSetTarget, receiverType);
+
+    ExpressionInferenceResult indexResult = inferrer
+        .inferExpression(node.index, indexType, true, isVoidAllowed: true);
+
+    inferrer.ensureAssignable(
+        indexType, indexResult.inferredType, node.index, node.index.fileOffset);
+
+    VariableDeclaration indexVariable =
+        createVariable(node.index, indexResult.inferredType);
+
+    ExpressionInferenceResult valueResult = inferrer
+        .inferExpression(node.value, valueType, true, isVoidAllowed: true);
+    inferrer.ensureAssignable(
+        valueType, valueResult.inferredType, node.value, node.value.fileOffset);
+    VariableDeclaration valueVariable =
+        createVariable(node.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,
+          wrapInSyntheticExpression: false);
+    } else if (indexSetTarget.isExtensionMember) {
+      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),
+          new Name('[]='),
+          new Arguments(<Expression>[
+            createVariableGet(indexVariable),
+            createVariableGet(valueVariable)
+          ])
+            ..fileOffset = node.fileOffset,
+          indexSetTarget.member)
+        ..fileOffset = node.fileOffset;
+    }
+    VariableDeclaration assignmentVariable =
+        createVariable(assignment, const VoidType());
+    node.replaceWith(replacement = new Let(
+        receiverVariable,
+        createLet(
+            indexVariable,
+            createLet(
+                valueVariable,
+                createLet(
+                    assignmentVariable, createVariableGet(valueVariable))))
+          ..fileOffset = node.fileOffset));
+    return new ExpressionInferenceResult(inferredType, replacement);
+  }
+
+  ExpressionInferenceResult visitIfNullIndexSet(
+      IfNullIndexSet node, DartType typeContext) {
+    ExpressionInferenceResult receiverResult = inferrer.inferExpression(
+        node.receiver, const UnknownType(), true,
+        isVoidAllowed: true);
+    DartType receiverType = receiverResult.inferredType;
+    VariableDeclaration receiverVariable =
+        createVariable(node.receiver, receiverType);
+
+    ObjectAccessTarget readTarget = inferrer.findInterfaceMember(
+        receiverType, new Name('[]'), node.readOffset,
+        includeExtensionMethods: true);
+
+    MethodContravarianceCheckKind checkKind =
+        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, new Name('=='), node.fileOffset)
+        .member;
+
+    ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
+        receiverType, new Name('[]='), node.fileOffset,
+        includeExtensionMethods: true);
+
+    DartType writeIndexType =
+        inferrer.getIndexKeyType(writeTarget, receiverType);
+    DartType valueType =
+        inferrer.getIndexSetValueType(writeTarget, receiverType);
+
+    ExpressionInferenceResult indexResult = inferrer
+        .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
+
+    VariableDeclaration indexVariable =
+        createVariable(node.index, indexResult.inferredType);
+
+    Expression readIndex = createVariableGet(indexVariable);
+    readIndex = inferrer.ensureAssignable(readIndexType,
+            indexResult.inferredType, readIndex, readIndex.fileOffset) ??
+        readIndex;
+
+    Expression writeIndex = createVariableGet(indexVariable);
+    writeIndex = inferrer.ensureAssignable(writeIndexType,
+            indexResult.inferredType, writeIndex, writeIndex.fileOffset) ??
+        writeIndex;
+
+    ExpressionInferenceResult valueResult = inferrer
+        .inferExpression(node.value, valueType, true, isVoidAllowed: true);
+    inferrer.ensureAssignable(
+        valueType, valueResult.inferredType, node.value, node.value.fileOffset);
+
+    DartType inferredType = inferrer.typeSchemaEnvironment
+        .getStandardUpperBound(readType, valueResult.inferredType);
+
+    Expression read;
+
+    if (readTarget.isMissing) {
+      read = inferrer.helper.buildProblem(
+          templateUndefinedMethod.withArguments('[]', receiverType),
+          node.readOffset,
+          '[]'.length,
+          wrapInSyntheticExpression: false);
+    } else if (readTarget.isExtensionMember) {
+      read = new StaticInvocation(
+          readTarget.member,
+          new Arguments(<Expression>[
+            createVariableGet(receiverVariable),
+            readIndex,
+          ], types: readTarget.inferredExtensionTypeArguments)
+            ..fileOffset = node.readOffset)
+        ..fileOffset = node.readOffset;
+    } else {
+      read = new MethodInvocation(
+          createVariableGet(receiverVariable),
+          new Name('[]'),
+          new Arguments(<Expression>[
+            readIndex,
+          ])
+            ..fileOffset = node.readOffset,
+          readTarget.member)
+        ..fileOffset = node.readOffset;
+
+      if (checkKind == MethodContravarianceCheckKind.checkMethodReturn) {
+        if (inferrer.instrumentation != null) {
+          inferrer.instrumentation.record(inferrer.uri, 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;
+    } else {
+      valueVariable = createVariable(node.value, valueResult.inferredType);
+      valueExpression = createVariableGet(valueVariable);
+    }
+
+    Expression write;
+
+    if (writeTarget.isMissing) {
+      write = inferrer.helper.buildProblem(
+          templateUndefinedMethod.withArguments('[]=', receiverType),
+          node.fileOffset,
+          '[]='.length,
+          wrapInSyntheticExpression: false);
+    } else if (writeTarget.isExtensionMember) {
+      write = new StaticInvocation(
+          writeTarget.member,
+          new Arguments(<Expression>[
+            createVariableGet(receiverVariable),
+            writeIndex,
+            valueExpression
+          ], types: writeTarget.inferredExtensionTypeArguments)
+            ..fileOffset = node.fileOffset)
+        ..fileOffset = node.fileOffset;
+    } else {
+      write = new MethodInvocation(
+          createVariableGet(receiverVariable),
+          new Name('[]='),
+          new Arguments(<Expression>[writeIndex, valueExpression])
+            ..fileOffset = node.fileOffset,
+          writeTarget.member)
+        ..fileOffset = node.fileOffset;
+    }
+
+    Expression replacement;
+    if (node.forEffect) {
+      // Encode `o[a] ??= b` as:
+      //
+      //     let v1 = o in
+      //     let v2 = a in
+      //     let v3 = v1[v2] in
+      //        v3 == null ? v1.[]=(v2, b) : null
+      //
+      MethodInvocation equalsNull =
+          createEqualsNull(node.fileOffset, read, equalsMember);
+      ConditionalExpression conditional = new ConditionalExpression(equalsNull,
+          write, new NullLiteral()..fileOffset = node.fileOffset, inferredType)
+        ..fileOffset = node.fileOffset;
+      node.replaceWith(replacement =
+          new Let(receiverVariable, createLet(indexVariable, conditional))
+            ..fileOffset = node.fileOffset);
+    } else {
+      // Encode `o[a] ??= b` as:
+      //
+      //     let v1 = o in
+      //     let v2 = a in
+      //     let v3 = v1[v2] in
+      //       v3 == null
+      //        ? (let v4 = b in
+      //           let _ = v1.[]=(v2, v4) in
+      //           v4)
+      //        : v3
+      //
+      assert(valueVariable != null);
+
+      VariableDeclaration readVariable = createVariable(read, readType);
+      MethodInvocation equalsNull = createEqualsNull(
+          node.fileOffset, createVariableGet(readVariable), equalsMember);
+      VariableDeclaration writeVariable =
+          createVariable(write, const VoidType());
+      ConditionalExpression conditional = new ConditionalExpression(
+          equalsNull,
+          createLet(valueVariable,
+              createLet(writeVariable, createVariableGet(valueVariable))),
+          createVariableGet(readVariable),
+          inferredType)
+        ..fileOffset = node.fileOffset;
+      node.replaceWith(replacement = new Let(receiverVariable,
+          createLet(indexVariable, createLet(readVariable, conditional)))
+        ..fileOffset = node.fileOffset);
+    }
+    return new ExpressionInferenceResult(inferredType, replacement);
+  }
+
+  ExpressionInferenceResult visitCompoundIndexSet(
+      CompoundIndexSet node, DartType typeContext) {
+    ExpressionInferenceResult receiverResult = inferrer.inferExpression(
+        node.receiver, const UnknownType(), true,
+        isVoidAllowed: true);
+    DartType receiverType = receiverResult.inferredType;
+    VariableDeclaration receiverVariable =
+        createVariable(node.receiver, receiverType);
+
+    ObjectAccessTarget readTarget = inferrer.findInterfaceMember(
+        receiverType, new Name('[]'), node.readOffset,
+        includeExtensionMethods: true);
+
+    MethodContravarianceCheckKind readCheckKind =
+        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);
+
+    Expression readIndex = createVariableGet(indexVariable);
+    Expression readIndexReplacement = inferrer.ensureAssignable(readIndexType,
+        indexResult.inferredType, readIndex, readIndex.fileOffset);
+    if (readIndexReplacement != null) {
+      readIndex = readIndexReplacement;
+    }
+
+    Expression read;
+    if (readTarget.isMissing) {
+      read = inferrer.helper.buildProblem(
+          templateUndefinedMethod.withArguments('[]', receiverType),
+          node.readOffset,
+          '[]'.length,
+          wrapInSyntheticExpression: false);
+    } else if (readTarget.isExtensionMember) {
+      read = new StaticInvocation(
+          readTarget.member,
+          new Arguments(<Expression>[
+            createVariableGet(receiverVariable),
+            readIndex,
+          ], types: readTarget.inferredExtensionTypeArguments)
+            ..fileOffset = node.readOffset)
+        ..fileOffset = node.readOffset;
+    } else {
+      read = new MethodInvocation(
+          createVariableGet(receiverVariable),
+          new Name('[]'),
+          new Arguments(<Expression>[
+            readIndex,
+          ])
+            ..fileOffset = node.readOffset,
+          readTarget.member)
+        ..fileOffset = node.readOffset;
+      if (readCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
+        if (inferrer.instrumentation != null) {
+          inferrer.instrumentation.record(inferrer.uri, node.readOffset,
+              'checkReturn', new InstrumentationValueForType(readType));
+        }
+        read = new AsExpression(read, readType)
+          ..isTypeError = true
+          ..fileOffset = node.readOffset;
+      }
+    }
+
+    VariableDeclaration leftVariable;
+    Expression left;
+    if (node.forEffect) {
+      left = read;
+    } else if (node.forPostIncDec) {
+      leftVariable = createVariable(read, readType);
+      left = createVariableGet(leftVariable);
+    } else {
+      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, receiverType),
+          node.binaryOffset,
+          node.binaryName.name.length,
+          wrapInSyntheticExpression: false);
+    } 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.uri, node.binaryOffset,
+              'checkReturn', new InstrumentationValueForType(readType));
+        }
+        binary = new AsExpression(binary, binaryType)
+          ..isTypeError = true
+          ..fileOffset = node.binaryOffset;
+      }
+    }
+
+    ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
+        receiverType, new Name('[]='), node.writeOffset,
+        includeExtensionMethods: true);
+
+    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;
+    }
+
+    DartType valueType =
+        inferrer.getIndexSetValueType(writeTarget, receiverType);
+    Expression binaryReplacement = inferrer.ensureAssignable(
+        valueType, binaryType, binary, node.fileOffset);
+    if (binaryReplacement != null) {
+      binary = binaryReplacement;
+    }
+
+    Expression replacement;
+
+    VariableDeclaration valueVariable;
+    Expression valueExpression;
+    if (node.forEffect || node.forPostIncDec) {
+      valueExpression = binary;
+    } else {
+      valueVariable = createVariable(binary, binaryType);
+      valueExpression = createVariableGet(valueVariable);
+    }
+
+    Expression write;
+
+    if (writeTarget.isMissing) {
+      write = inferrer.helper.buildProblem(
+          templateUndefinedMethod.withArguments('[]=', receiverType),
+          node.writeOffset,
+          '[]='.length,
+          wrapInSyntheticExpression: false);
+    } else if (writeTarget.isExtensionMember) {
+      write = new StaticInvocation(
+          writeTarget.member,
+          new Arguments(<Expression>[
+            createVariableGet(receiverVariable),
+            writeIndex,
+            valueExpression
+          ], types: writeTarget.inferredExtensionTypeArguments)
+            ..fileOffset = node.writeOffset)
+        ..fileOffset = node.writeOffset;
+    } else {
+      write = new MethodInvocation(
+          createVariableGet(receiverVariable),
+          new Name('[]='),
+          new Arguments(<Expression>[writeIndex, valueExpression])
+            ..fileOffset = node.writeOffset,
+          writeTarget.member)
+        ..fileOffset = node.writeOffset;
+    }
+
+    if (node.forEffect) {
+      assert(leftVariable == null);
+      assert(valueVariable == null);
+      // Encode `o[a] += b` as:
+      //
+      //     let v1 = o in let v2 = a in v1.[]=(v2, v1.[](v2) + b)
+      //
+      node.replaceWith(replacement =
+          new Let(receiverVariable, createLet(indexVariable, write))
+            ..fileOffset = node.fileOffset);
+    } else if (node.forPostIncDec) {
+      // Encode `o[a]++` as:
+      //
+      //     let v1 = o in
+      //     let v2 = a in
+      //     let v3 = v1.[](v2)
+      //     let v4 = v1.[]=(v2, c3 + b) in v3
+      //
+      assert(leftVariable != null);
+      assert(valueVariable == null);
+
+      VariableDeclaration writeVariable =
+          createVariable(write, const VoidType());
+      node.replaceWith(replacement = new Let(
+          receiverVariable,
+          createLet(
+              indexVariable,
+              createLet(leftVariable,
+                  createLet(writeVariable, createVariableGet(leftVariable)))))
+        ..fileOffset = node.fileOffset);
+    } else {
+      // Encode `o[a] += b` as:
+      //
+      //     let v1 = o in
+      //     let v2 = a in
+      //     let v3 = v1.[](v2) + b
+      //     let v4 = v1.[]=(v2, c3) in v3
+      //
+      assert(leftVariable == null);
+      assert(valueVariable != null);
+
+      VariableDeclaration writeVariable =
+          createVariable(write, const VoidType());
+      node.replaceWith(replacement = new Let(
+          receiverVariable,
+          createLet(
+              indexVariable,
+              createLet(valueVariable,
+                  createLet(writeVariable, createVariableGet(valueVariable)))))
+        ..fileOffset = node.fileOffset);
+    }
+    return new ExpressionInferenceResult(
+        node.forPostIncDec ? readType : binaryType, replacement);
   }
 
   @override
   ExpressionInferenceResult visitNullLiteral(
-          NullLiteral node, DartType typeContext) =>
-      new ExpressionInferenceResult(inferrer.coreTypes.nullClass.rawType);
+      NullLiteral node, DartType typeContext) {
+    return new ExpressionInferenceResult(inferrer.coreTypes.nullType);
+  }
 
   @override
   ExpressionInferenceResult visitLet(Let node, DartType typeContext) {
@@ -1665,18 +2634,53 @@
     if (variableType == const DynamicType()) {
       return defaultExpression(node, typeContext);
     }
-    Expression initializer = node.variable.initializer;
-    inferrer.inferExpression(initializer, variableType, true,
+    inferrer.inferExpression(node.variable.initializer, variableType, true,
         isVoidAllowed: true);
-    Expression body = node.body;
-    ExpressionInferenceResult result =
-        inferrer.inferExpression(body, typeContext, true, isVoidAllowed: true);
+    ExpressionInferenceResult result = inferrer
+        .inferExpression(node.body, typeContext, true, isVoidAllowed: true);
     DartType inferredType = result.inferredType;
-    // TODO(ahe): This shouldn't be needed. See InferredTypeVisitor.visitLet.
-    inferrer.storeInferredType(node, inferredType);
     return new ExpressionInferenceResult(inferredType);
   }
 
+  @override
+  ExpressionInferenceResult visitPropertySet(
+      PropertySet node, DartType typeContext) {
+    DartType receiverType;
+    if (node.receiver != null) {
+      receiverType = inferrer
+          .inferExpression(node.receiver, const UnknownType(), true)
+          .inferredType;
+    } else {
+      receiverType = inferrer.thisType;
+    }
+    ObjectAccessTarget target =
+        inferrer.findPropertySetMember(receiverType, node);
+    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) {
+      node.parent.replaceChild(
+          node,
+          replacement = inferrer.helper.forest.createStaticInvocation(
+              node.fileOffset,
+              target.member,
+              inferrer.helper.forest.createArgumentsForExtensionMethod(
+                  node.fileOffset,
+                  target.inferredExtensionTypeArguments.length,
+                  0,
+                  node.receiver,
+                  extensionTypeArguments: target.inferredExtensionTypeArguments,
+                  positionalArguments: [node.value])));
+    }
+    return new ExpressionInferenceResult(rhsType, replacement);
+  }
+
   ExpressionInferenceResult visitPropertyAssignmentJudgment(
       PropertyAssignmentJudgment node, DartType typeContext) {
     DartType receiverType = node._inferReceiver(inferrer);
@@ -1705,7 +2709,7 @@
     DartType writeContext = inferrer.getSetterType(writeTarget, receiverType);
     DartType inferredType =
         node._inferRhs(inferrer, readType, writeContext).inferredType;
-    node.nullAwareGuard?.staticType = node.inferredType;
+    node.nullAwareGuard?.staticType = inferredType;
     Expression replacement;
     if (writeTarget.isExtensionMember) {
       node.parent.replaceChild(
@@ -1721,7 +2725,6 @@
                   extensionTypeArguments:
                       writeTarget.inferredExtensionTypeArguments,
                   positionalArguments: [node.rhs])));
-      inferrer.storeInferredType(replacement, inferredType);
     } else {
       node._replaceWithDesugared();
     }
@@ -1733,12 +2736,11 @@
   ExpressionInferenceResult visitPropertyGet(
       PropertyGet node, DartType typeContext) {
     return inferrer.inferPropertyGet(
-        node, node.receiver, node.fileOffset, typeContext,
-        desugaredGet: node, allowExtensionMethods: true);
+        node, node.receiver, node.fileOffset, typeContext, node);
   }
 
-  void visitRedirectingInitializerJudgment(
-      RedirectingInitializerJudgment node) {
+  @override
+  void visitRedirectingInitializer(RedirectingInitializer node) {
     List<TypeParameter> classTypeParameters =
         node.target.enclosingClass.typeParameters;
     List<DartType> typeArguments =
@@ -1746,41 +2748,43 @@
     for (int i = 0; i < typeArguments.length; i++) {
       typeArguments[i] = new TypeParameterType(classTypeParameters[i]);
     }
-    ArgumentsJudgment.setNonInferrableArgumentTypes(
-        node.arguments, typeArguments);
+    ArgumentsImpl.setNonInferrableArgumentTypes(node.arguments, typeArguments);
     inferrer.inferInvocation(
         null,
         node.fileOffset,
-        node.target.function.functionType,
+        node.target.function.thisFunctionType,
         node.target.enclosingClass.thisType,
-        node.argumentJudgments,
+        node.arguments,
         skipTypeArgumentInference: true);
-    ArgumentsJudgment.removeNonInferrableArgumentTypes(node.arguments);
+    ArgumentsImpl.removeNonInferrableArgumentTypes(node.arguments);
   }
 
   @override
-  ExpressionInferenceResult visitRethrow(Rethrow node, DartType typeContext) =>
-      const ExpressionInferenceResult(const BottomType());
+  ExpressionInferenceResult visitRethrow(Rethrow node, DartType typeContext) {
+    return const ExpressionInferenceResult(const BottomType());
+  }
 
-  void visitReturnJudgment(ReturnJudgment node) {
-    Expression judgment = node.judgment;
+  @override
+  void visitReturnStatement(covariant ReturnStatementImpl node) {
     ClosureContext closureContext = inferrer.closureContext;
     DartType typeContext = !closureContext.isGenerator
         ? closureContext.returnOrYieldContext
         : const UnknownType();
     DartType inferredType;
     if (node.expression != null) {
-      inferrer.inferExpression(judgment, typeContext, true,
-          isVoidAllowed: true);
-      inferredType = getInferredType(judgment, inferrer);
+      inferredType = inferrer
+          .inferExpression(node.expression, typeContext, true,
+              isVoidAllowed: true)
+          .inferredType;
     } else {
-      inferredType = inferrer.coreTypes.nullClass.rawType;
+      inferredType = inferrer.coreTypes.nullType;
     }
     closureContext.handleReturn(inferrer, node, inferredType, node.isArrow);
   }
 
-  ExpressionInferenceResult visitSetLiteralJudgment(
-      SetLiteralJudgment node, DartType typeContext) {
+  @override
+  ExpressionInferenceResult visitSetLiteral(
+      SetLiteral node, DartType typeContext) {
     Class setClass = inferrer.coreTypes.setClass;
     InterfaceType setType = setClass.thisType;
     List<DartType> inferredTypes;
@@ -1790,10 +2794,12 @@
     bool inferenceNeeded = node.typeArgument is ImplicitTypeArgument;
     bool typeChecksNeeded = !inferrer.isTopLevel;
     Map<TreeNode, DartType> inferredSpreadTypes;
+    Map<Expression, DartType> inferredConditionTypes;
     if (inferenceNeeded || typeChecksNeeded) {
       formalTypes = [];
       actualTypes = [];
       inferredSpreadTypes = new Map<TreeNode, DartType>.identity();
+      inferredConditionTypes = new Map<Expression, DartType>.identity();
     }
     if (inferenceNeeded) {
       inferredTypes = [const UnknownType()];
@@ -1811,6 +2817,7 @@
             node,
             inferredTypeArgument,
             inferredSpreadTypes,
+            inferredConditionTypes,
             inferenceNeeded,
             typeChecksNeeded);
         actualTypes.add(type);
@@ -1837,11 +2844,11 @@
     }
     if (typeChecksNeeded) {
       for (int i = 0; i < node.expressions.length; i++) {
-        checkElement(
-            node.expressions[i], node, node.typeArgument, inferredSpreadTypes);
+        checkElement(node.expressions[i], node, node.typeArgument,
+            inferredSpreadTypes, inferredConditionTypes);
       }
     }
-    node.inferredType = new InterfaceType(setClass, [inferredTypeArgument]);
+    DartType inferredType = new InterfaceType(setClass, [inferredTypeArgument]);
     if (!inferrer.isTopLevel) {
       SourceLibraryBuilder library = inferrer.library;
       if (inferenceNeeded) {
@@ -1854,7 +2861,23 @@
         inferrer.helper.transformSetLiterals = true;
       }
     }
-    return new ExpressionInferenceResult(node.inferredType);
+    return new ExpressionInferenceResult(inferredType);
+  }
+
+  @override
+  ExpressionInferenceResult visitStaticSet(
+      StaticSet node, DartType typeContext) {
+    Member writeMember = node.target;
+    DartType writeContext = writeMember.setterType;
+    TypeInferenceEngine.resolveInferenceNode(writeMember);
+    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);
   }
 
   ExpressionInferenceResult visitStaticAssignmentJudgment(
@@ -1888,7 +2911,6 @@
     if (target is Procedure && target.kind == ProcedureKind.Method) {
       type = inferrer.instantiateTearOff(type, typeContext, node);
     }
-    inferrer.storeInferredType(node, type);
     return new ExpressionInferenceResult(type);
   }
 
@@ -1902,7 +2924,6 @@
         getExplicitTypeArguments(node.arguments) != null;
     DartType inferredType = inferrer.inferInvocation(typeContext,
         node.fileOffset, calleeType, calleeType.returnType, node.arguments);
-    inferrer.storeInferredType(node, inferredType);
     if (!inferrer.isTopLevel &&
         !hadExplicitTypeArguments &&
         node.target != null) {
@@ -1923,15 +2944,18 @@
       }
     }
     return new ExpressionInferenceResult(
-        inferrer.coreTypes.stringClass.rawType);
+        inferrer.coreTypes.stringRawType(inferrer.library.nonNullable));
   }
 
   @override
   ExpressionInferenceResult visitStringLiteral(
-          StringLiteral node, DartType typeContext) =>
-      new ExpressionInferenceResult(inferrer.coreTypes.stringClass.rawType);
+      StringLiteral node, DartType typeContext) {
+    return new ExpressionInferenceResult(
+        inferrer.coreTypes.stringRawType(inferrer.library.nonNullable));
+  }
 
-  void visitSuperInitializerJudgment(SuperInitializerJudgment node) {
+  @override
+  void visitSuperInitializer(SuperInitializer node) {
     Substitution substitution = Substitution.fromSupertype(
         inferrer.classHierarchy.getClassAsInstanceOf(
             inferrer.thisType.classNode, node.target.enclosingClass));
@@ -1939,51 +2963,80 @@
         null,
         node.fileOffset,
         substitution.substituteType(
-            node.target.function.functionType.withoutTypeParameters),
+            node.target.function.thisFunctionType.withoutTypeParameters),
         inferrer.thisType,
-        node.argumentJudgments,
+        node.arguments,
         skipTypeArgumentInference: true);
   }
 
-  ExpressionInferenceResult visitSuperMethodInvocationJudgment(
-      SuperMethodInvocationJudgment node, DartType typeContext) {
+  @override
+  ExpressionInferenceResult visitSuperMethodInvocation(
+      SuperMethodInvocation node, DartType typeContext) {
     if (node.interfaceTarget != null) {
       inferrer.instrumentation?.record(inferrer.uri, node.fileOffset, 'target',
           new InstrumentationValueForMember(node.interfaceTarget));
     }
-    ExpressionInferenceResult result = inferrer.inferMethodInvocation(
-        node, null, node.fileOffset, false, typeContext,
-        target: node.interfaceTarget != null
+    ExpressionInferenceResult result = inferrer.inferSuperMethodInvocation(
+        node,
+        typeContext,
+        node.interfaceTarget != null
             ? new ObjectAccessTarget.interfaceMember(node.interfaceTarget)
-            : const ObjectAccessTarget.unresolved(),
-        methodName: node.name,
-        arguments: node.arguments);
-    node.inferredType = result.inferredType;
+            : const ObjectAccessTarget.unresolved());
     return new ExpressionInferenceResult(result.inferredType);
   }
 
-  ExpressionInferenceResult visitSuperPropertyGetJudgment(
-      SuperPropertyGetJudgment node, DartType typeContext) {
+  @override
+  ExpressionInferenceResult visitSuperPropertyGet(
+      SuperPropertyGet node, DartType typeContext) {
     if (node.interfaceTarget != null) {
       inferrer.instrumentation?.record(inferrer.uri, node.fileOffset, 'target',
           new InstrumentationValueForMember(node.interfaceTarget));
     }
-    return inferrer.inferPropertyGet(node, null, node.fileOffset, typeContext,
-        readTarget: node.interfaceTarget != null
+    return inferrer.inferSuperPropertyGet(
+        node,
+        typeContext,
+        node.interfaceTarget != null
             ? new ObjectAccessTarget.interfaceMember(node.interfaceTarget)
-            : const ObjectAccessTarget.unresolved(),
-        propertyName: node.name);
+            : const ObjectAccessTarget.unresolved());
   }
 
-  void visitSwitchStatementJudgment(SwitchStatementJudgment node) {
-    Expression expressionJudgment = node.expressionJudgment;
-    inferrer.inferExpression(expressionJudgment, const UnknownType(), true);
-    DartType expressionType = getInferredType(expressionJudgment, inferrer);
+  @override
+  ExpressionInferenceResult visitSuperPropertySet(
+      SuperPropertySet node, DartType typeContext) {
+    DartType receiverType = inferrer.classHierarchy.getTypeAsInstanceOf(
+        inferrer.thisType, inferrer.thisType.classNode.supertype.classNode);
 
-    for (SwitchCaseJudgment switchCase in node.caseJudgments) {
-      for (Expression caseExpression in switchCase.expressionJudgments) {
+    ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
+        receiverType, node.name, node.fileOffset,
+        setter: true, instrumented: true);
+    if (writeTarget.isInstanceMember) {
+      node.interfaceTarget = writeTarget.member;
+    }
+    DartType writeContext = inferrer.getSetterType(writeTarget, 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);
+
+    return new ExpressionInferenceResult(rhsType);
+  }
+
+  @override
+  void visitSwitchStatement(SwitchStatement node) {
+    DartType expressionType = inferrer
+        .inferExpression(node.expression, const UnknownType(), true)
+        .inferredType;
+
+    for (SwitchCase switchCase in node.cases) {
+      for (Expression caseExpression in switchCase.expressions) {
         ExpressionInferenceResult caseExpressionResult =
             inferrer.inferExpression(caseExpression, expressionType, true);
+        if (caseExpressionResult.replacement != null) {
+          caseExpression = caseExpressionResult.replacement;
+        }
         DartType caseExpressionType = caseExpressionResult.inferredType;
 
         // Check whether the expression type is assignable to the case
@@ -1996,7 +3049,7 @@
               noLength,
               context: [
                 messageSwitchExpressionNotAssignableCause.withLocation(
-                    inferrer.uri, expressionJudgment.fileOffset, noLength)
+                    inferrer.uri, node.expression.fileOffset, noLength)
               ]);
         }
       }
@@ -2004,10 +3057,12 @@
     }
   }
 
-  ExpressionInferenceResult visitSymbolLiteralJudgment(
-      SymbolLiteralJudgment node, DartType typeContext) {
-    node.inferredType = inferrer.coreTypes.symbolClass.rawType;
-    return new ExpressionInferenceResult(node.inferredType);
+  @override
+  ExpressionInferenceResult visitSymbolLiteral(
+      SymbolLiteral node, DartType typeContext) {
+    DartType inferredType =
+        inferrer.coreTypes.symbolRawType(inferrer.library.nonNullable);
+    return new ExpressionInferenceResult(inferredType);
   }
 
   ExpressionInferenceResult visitInvalidConstructorInvocationJudgment(
@@ -2015,16 +3070,16 @@
     FunctionType calleeType;
     DartType returnType;
     if (node.constructor != null) {
-      calleeType = node.constructor.function.functionType;
+      calleeType = node.constructor.function.thisFunctionType;
       returnType = computeConstructorReturnType(node.constructor);
     } else {
       calleeType = new FunctionType([], const DynamicType());
       returnType = const DynamicType();
     }
-    DartType inferredType = inferrer.inferInvocation(typeContext,
-        node.fileOffset, calleeType, returnType, node.argumentJudgments);
-    node.inferredType = inferredType;
-    return visitSyntheticExpressionJudgment(node, typeContext);
+    DartType inferredType = inferrer.inferInvocation(
+        typeContext, node.fileOffset, calleeType, returnType, node.arguments);
+    node._replaceWithDesugared();
+    return new ExpressionInferenceResult(inferredType);
   }
 
   ExpressionInferenceResult visitInvalidWriteJudgment(
@@ -2042,13 +3097,13 @@
   ExpressionInferenceResult visitSyntheticExpressionJudgment(
       SyntheticExpressionJudgment node, DartType typeContext) {
     node._replaceWithDesugared();
-    node.inferredType = const DynamicType();
     return const ExpressionInferenceResult(const DynamicType());
   }
 
   ExpressionInferenceResult visitThisExpression(
-          ThisExpression node, DartType typeContext) =>
-      new ExpressionInferenceResult(inferrer.thisType);
+      ThisExpression node, DartType typeContext) {
+    return new ExpressionInferenceResult(inferrer.thisType);
+  }
 
   @override
   ExpressionInferenceResult visitThrow(Throw node, DartType typeContext) {
@@ -2057,26 +3112,44 @@
     return const ExpressionInferenceResult(const BottomType());
   }
 
-  void visitCatchJudgment(CatchJudgment node) {
+  void visitCatch(Catch node) {
     inferrer.inferStatement(node.body);
   }
 
-  void visitTryCatchJudgment(TryCatchJudgment node) {
+  @override
+  void visitTryCatch(TryCatch node) {
     inferrer.inferStatement(node.body);
-    for (CatchJudgment catch_ in node.catchJudgments) {
-      visitCatchJudgment(catch_);
+    for (Catch catch_ in node.catches) {
+      visitCatch(catch_);
     }
   }
 
-  void visitTryFinallyJudgment(TryFinallyJudgment node) {
+  @override
+  void visitTryFinally(TryFinally node) {
     inferrer.inferStatement(node.body);
     inferrer.inferStatement(node.finalizer);
   }
 
-  ExpressionInferenceResult visitTypeLiteralJudgment(
-      TypeLiteralJudgment node, DartType typeContext) {
-    node.inferredType = inferrer.coreTypes.typeClass.rawType;
-    return new ExpressionInferenceResult(node.inferredType);
+  @override
+  ExpressionInferenceResult visitTypeLiteral(
+      TypeLiteral node, DartType typeContext) {
+    DartType inferredType =
+        inferrer.coreTypes.typeRawType(inferrer.library.nonNullable);
+    return new ExpressionInferenceResult(inferredType);
+  }
+
+  @override
+  ExpressionInferenceResult visitVariableSet(
+      VariableSet node, DartType typeContext) {
+    DartType writeContext = node.variable.type;
+    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);
   }
 
   ExpressionInferenceResult visitVariableAssignmentJudgment(
@@ -2100,15 +3173,15 @@
     return new ExpressionInferenceResult(inferredType);
   }
 
-  void visitVariableDeclarationJudgment(VariableDeclarationJudgment node) {
-    Expression initializerJudgment = node.initializerJudgment;
+  @override
+  void visitVariableDeclaration(covariant VariableDeclarationImpl node) {
     DartType declaredType =
         node._implicitlyTyped ? const UnknownType() : node.type;
     DartType inferredType;
     DartType initializerType;
-    if (initializerJudgment != null) {
+    if (node.initializer != null) {
       ExpressionInferenceResult initializerResult = inferrer.inferExpression(
-          initializerJudgment,
+          node.initializer,
           declaredType,
           !inferrer.isTopLevel || node._implicitlyTyped,
           isVoidAllowed: true);
@@ -2155,16 +3228,18 @@
 
   ExpressionInferenceResult visitUnresolvedVariableAssignmentJudgment(
       UnresolvedVariableAssignmentJudgment node, DartType typeContext) {
-    inferrer.inferExpression(node.rhs, const UnknownType(), true);
-    node.inferredType = node.isCompound
-        ? const DynamicType()
-        : getInferredType(node.rhs, inferrer);
-    return visitSyntheticExpressionJudgment(node, typeContext);
+    DartType rhsType = inferrer
+        .inferExpression(node.rhs, const UnknownType(), true)
+        .inferredType;
+    DartType inferredType = node.isCompound ? const DynamicType() : rhsType;
+    node._replaceWithDesugared();
+    return new ExpressionInferenceResult(inferredType);
   }
 
-  ExpressionInferenceResult visitVariableGetJudgment(
-      VariableGetJudgment node, DartType typeContext) {
-    VariableDeclarationJudgment variable = node.variable;
+  @override
+  ExpressionInferenceResult visitVariableGet(
+      covariant VariableGetImpl node, DartType typeContext) {
+    VariableDeclarationImpl variable = node.variable;
     bool mutatedInClosure = variable._mutatedInClosure;
     DartType declaredOrInferredType = variable.type;
 
@@ -2179,26 +3254,25 @@
     if (variable._isLocalFunction) {
       type = inferrer.instantiateTearOff(type, typeContext, node);
     }
-    node.inferredType = type;
     return new ExpressionInferenceResult(type);
   }
 
-  void visitWhileJudgment(WhileJudgment node) {
-    Expression conditionJudgment = node.conditionJudgment;
-    InterfaceType expectedType = inferrer.coreTypes.boolClass.rawType;
-    inferrer.inferExpression(
-        conditionJudgment, expectedType, !inferrer.isTopLevel);
+  @override
+  void visitWhileStatement(WhileStatement node) {
+    InterfaceType expectedType =
+        inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
+    DartType conditionType = inferrer
+        .inferExpression(node.condition, expectedType, !inferrer.isTopLevel)
+        .inferredType;
     inferrer.ensureAssignable(
-        expectedType,
-        getInferredType(conditionJudgment, inferrer),
-        node.condition,
-        node.condition.fileOffset);
+        expectedType, conditionType, node.condition, node.condition.fileOffset);
     inferrer.inferStatement(node.body);
   }
 
-  void visitYieldJudgment(YieldJudgment node) {
-    Expression judgment = node.judgment;
+  @override
+  void visitYieldStatement(YieldStatement node) {
     ClosureContext closureContext = inferrer.closureContext;
+    DartType inferredType;
     if (closureContext.isGenerator) {
       DartType typeContext = closureContext.returnOrYieldContext;
       if (node.isYieldStar && typeContext != null) {
@@ -2208,35 +3282,44 @@
                 ? inferrer.coreTypes.streamClass
                 : inferrer.coreTypes.iterableClass);
       }
-      inferrer.inferExpression(judgment, typeContext, true);
+      inferredType = inferrer
+          .inferExpression(node.expression, typeContext, true)
+          .inferredType;
     } else {
-      inferrer.inferExpression(judgment, const UnknownType(), true);
+      inferredType = inferrer
+          .inferExpression(node.expression, const UnknownType(), true)
+          .inferredType;
     }
-    closureContext.handleYield(inferrer, node.isYieldStar,
-        getInferredType(judgment, inferrer), node.expression, node.fileOffset);
+    closureContext.handleYield(inferrer, node.isYieldStar, inferredType,
+        node.expression, node.fileOffset);
   }
 
-  ExpressionInferenceResult visitLoadLibraryJudgment(
-      LoadLibraryJudgment node, DartType typeContext) {
-    node.inferredType =
+  @override
+  ExpressionInferenceResult visitLoadLibrary(
+      covariant LoadLibraryImpl node, DartType typeContext) {
+    DartType inferredType =
         inferrer.typeSchemaEnvironment.futureType(const DynamicType());
     if (node.arguments != null) {
-      FunctionType calleeType = new FunctionType([], node.inferredType);
+      FunctionType calleeType = new FunctionType([], inferredType);
       inferrer.inferInvocation(typeContext, node.fileOffset, calleeType,
-          calleeType.returnType, node.argumentJudgments);
+          calleeType.returnType, node.arguments);
     }
-    return new ExpressionInferenceResult(node.inferredType);
+    return new ExpressionInferenceResult(inferredType);
   }
 
-  ExpressionInferenceResult visitLoadLibraryTearOffJudgment(
-      LoadLibraryTearOffJudgment node, DartType typeContext) {
-    node.inferredType = new FunctionType(
+  ExpressionInferenceResult visitLoadLibraryTearOff(
+      LoadLibraryTearOff node, DartType typeContext) {
+    DartType inferredType = new FunctionType(
         [], inferrer.typeSchemaEnvironment.futureType(const DynamicType()));
-    return new ExpressionInferenceResult(node.inferredType);
+    Expression replacement = node.replace();
+    return new ExpressionInferenceResult(inferredType, replacement);
   }
 
   @override
   ExpressionInferenceResult visitCheckLibraryIsLoaded(
-          CheckLibraryIsLoaded node, DartType typeContext) =>
-      new ExpressionInferenceResult(inferrer.coreTypes.objectClass.rawType);
+      CheckLibraryIsLoaded node, DartType typeContext) {
+    // TODO(dmitryas): Figure out the suitable nullability for that.
+    return new ExpressionInferenceResult(
+        inferrer.coreTypes.objectRawType(inferrer.library.nullable));
+  }
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/inferred_type_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inferred_type_visitor.dart
deleted file mode 100644
index 05513ad..0000000
--- a/pkg/front_end/lib/src/fasta/kernel/inferred_type_visitor.dart
+++ /dev/null
@@ -1,162 +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.
-
-part of "kernel_shadow_ast.dart";
-
-DartType getInferredType(Expression expression, TypeInferrerImpl inferrer) {
-  if (expression is ExpressionJudgment) {
-    return expression.inferredType;
-  } else {
-    return expression.accept1(const InferredTypeVisitor(), inferrer);
-  }
-}
-
-DartType invalidToBottom(DartType type) {
-  // TODO(ahe): This should really return [BottomType], but that requires more
-  // work to the Kernel type system and implementation.
-  return (type == null || type is InvalidType) ? const DynamicType() : type;
-}
-
-DartType invalidToTop(DartType type) {
-  return (type == null || type is InvalidType) ? const DynamicType() : type;
-}
-
-class InferredTypeVisitor
-    extends ExpressionVisitor1<DartType, TypeInferrerImpl> {
-  const InferredTypeVisitor();
-
-  @override
-  DartType defaultExpression(Expression node, TypeInferrerImpl inferrer) {
-    unhandled("${node.runtimeType}", "getInferredType", node.fileOffset,
-        inferrer.uri);
-    return const InvalidType();
-  }
-
-  @override
-  DartType visitIntLiteral(IntLiteral node, TypeInferrerImpl inferrer) {
-    return inferrer.coreTypes.intClass.rawType;
-  }
-
-  @override
-  DartType visitDoubleLiteral(DoubleLiteral node, TypeInferrerImpl inferrer) {
-    return inferrer.coreTypes.doubleClass.rawType;
-  }
-
-  @override
-  DartType visitInvalidExpression(
-      InvalidExpression node, TypeInferrerImpl inferrer) {
-    return const BottomType();
-  }
-
-  @override
-  DartType visitAsExpression(AsExpression node, TypeInferrerImpl inferrer) {
-    return invalidToBottom(node.type);
-  }
-
-  @override
-  DartType visitAwaitExpression(
-      AwaitExpression node, TypeInferrerImpl inferrer) {
-    return inferrer.readInferredType(node);
-  }
-
-  @override
-  DartType visitThisExpression(ThisExpression node, TypeInferrerImpl inferrer) {
-    return invalidToBottom(inferrer.thisType);
-  }
-
-  @override
-  DartType visitBoolLiteral(BoolLiteral node, TypeInferrerImpl inferrer) {
-    return inferrer.coreTypes.boolClass.rawType;
-  }
-
-  @override
-  DartType visitConditionalExpression(
-      ConditionalExpression node, TypeInferrerImpl inferrer) {
-    return node.staticType;
-  }
-
-  @override
-  DartType visitConstructorInvocation(
-      ConstructorInvocation node, TypeInferrerImpl inferrer) {
-    return inferrer.readInferredType(node);
-  }
-
-  @override
-  DartType visitIsExpression(IsExpression node, TypeInferrerImpl inferrer) {
-    return inferrer.coreTypes.boolClass.rawType;
-  }
-
-  @override
-  DartType visitFunctionExpression(
-      FunctionExpression node, TypeInferrerImpl inferrer) {
-    return inferrer.readInferredType(node);
-  }
-
-  @override
-  DartType visitLogicalExpression(
-      LogicalExpression node, TypeInferrerImpl inferrer) {
-    return inferrer.coreTypes.boolClass.rawType;
-  }
-
-  @override
-  DartType visitNot(Not node, TypeInferrerImpl inferrer) {
-    return inferrer.coreTypes.boolClass.rawType;
-  }
-
-  @override
-  DartType visitNullLiteral(NullLiteral node, TypeInferrerImpl inferrer) {
-    return inferrer.coreTypes.nullClass.rawType;
-  }
-
-  @override
-  DartType visitPropertyGet(PropertyGet node, TypeInferrerImpl inferrer) {
-    return inferrer.readInferredType(node);
-  }
-
-  @override
-  DartType visitRethrow(Rethrow node, TypeInferrerImpl inferrer) {
-    return const BottomType();
-  }
-
-  @override
-  DartType visitStringConcatenation(
-      StringConcatenation node, TypeInferrerImpl inferrer) {
-    return inferrer.coreTypes.stringClass.rawType;
-  }
-
-  @override
-  DartType visitStringLiteral(StringLiteral node, TypeInferrerImpl inferrer) {
-    return inferrer.coreTypes.stringClass.rawType;
-  }
-
-  @override
-  DartType visitLet(Let node, TypeInferrerImpl inferrer) {
-    // TODO(ahe): We should be able to return the inferred type of
-    // node.body. However, that type may be lost, for example, in
-    // VariableAssignmentJudgment._replaceWithDesugared.
-    return inferrer.readInferredType(node);
-  }
-
-  @override
-  DartType visitStaticGet(StaticGet node, TypeInferrerImpl inferrer) {
-    return inferrer.readInferredType(node);
-  }
-
-  @override
-  DartType visitStaticInvocation(
-      StaticInvocation node, TypeInferrerImpl inferrer) {
-    return inferrer.readInferredType(node);
-  }
-
-  @override
-  DartType visitThrow(Throw node, TypeInferrerImpl inferrer) {
-    return const BottomType();
-  }
-
-  @override
-  DartType visitCheckLibraryIsLoaded(
-      CheckLibraryIsLoaded node, TypeInferrerImpl inferrer) {
-    return inferrer.coreTypes.objectClass.rawType;
-  }
-}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
index bca9db5..65f8ccf 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
@@ -84,37 +84,22 @@
 
 export 'kernel_shadow_ast.dart'
     show
-        ArgumentsJudgment,
-        AssertInitializerJudgment,
-        AssertStatementJudgment,
-        BlockJudgment,
-        CascadeJudgment,
+        ArgumentsImpl,
+        Cascade,
         ComplexAssignmentJudgment,
-        ContinueSwitchJudgment,
-        DeferredCheckJudgment,
-        ExpressionStatementJudgment,
+        DeferredCheck,
         FactoryConstructorInvocationJudgment,
-        FunctionDeclarationJudgment,
-        FunctionNodeJudgment,
-        IfJudgment,
+        FunctionDeclarationImpl,
         IfNullJudgment,
         InvalidSuperInitializerJudgment,
-        LoadLibraryTearOffJudgment,
-        MethodInvocationJudgment,
+        LoadLibraryTearOff,
+        MethodInvocationImpl,
         NamedFunctionExpressionJudgment,
-        NullAwareMethodInvocationJudgment,
-        NullAwarePropertyGetJudgment,
-        RedirectingInitializerJudgment,
-        ReturnJudgment,
-        ShadowFieldInitializer,
+        NullAwareMethodInvocation,
+        NullAwarePropertyGet,
+        ReturnStatementImpl,
         ShadowInvalidFieldInitializer,
         ShadowInvalidInitializer,
         ShadowLargeIntLiteral,
-        SuperInitializerJudgment,
-        SuperMethodInvocationJudgment,
-        SuperPropertyGetJudgment,
-        SwitchCaseJudgment,
-        SwitchStatementJudgment,
-        VariableDeclarationJudgment,
-        VariableGetJudgment,
-        YieldJudgment;
+        VariableDeclarationImpl,
+        VariableGetImpl;
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 36e77d4..99d2714 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,8 +20,6 @@
 
 import 'dart:core' hide MapEntry;
 
-import 'package:kernel/ast.dart' as kernel show Expression, Initializer;
-
 import 'package:kernel/ast.dart';
 
 import 'package:kernel/type_algebra.dart' show Substitution;
@@ -53,6 +51,7 @@
         templateSpreadMapEntryTypeMismatch,
         templateSpreadTypeMismatch,
         templateSwitchExpressionNotAssignable,
+        templateUndefinedMethod,
         templateWebLiteralCannotBeRepresentedExactly;
 
 import '../problems.dart' show getFileUri, unhandled, unsupported;
@@ -98,7 +97,6 @@
 import 'implicit_type_argument.dart' show ImplicitTypeArgument;
 
 part "inference_visitor.dart";
-part "inferred_type_visitor.dart";
 
 /// Computes the return type of a (possibly factory) constructor.
 InterfaceType computeConstructorReturnType(Member constructor) {
@@ -110,7 +108,7 @@
 }
 
 int getExtensionTypeParameterCount(Arguments arguments) {
-  if (arguments is ArgumentsJudgment) {
+  if (arguments is ArgumentsImpl) {
     return arguments._extensionTypeParameterCount;
   } else {
     // TODO(johnniwinther): Remove this path or assert why it is accepted.
@@ -119,7 +117,7 @@
 }
 
 int getExtensionTypeArgumentCount(Arguments arguments) {
-  if (arguments is ArgumentsJudgment) {
+  if (arguments is ArgumentsImpl) {
     return arguments._extensionTypeArgumentCount;
   } else {
     // TODO(johnniwinther): Remove this path or assert why it is accepted.
@@ -128,7 +126,7 @@
 }
 
 List<DartType> getExplicitExtensionTypeArguments(Arguments arguments) {
-  if (arguments is ArgumentsJudgment) {
+  if (arguments is ArgumentsImpl) {
     if (arguments._extensionTypeArgumentCount == 0) {
       return null;
     } else {
@@ -143,7 +141,7 @@
 }
 
 List<DartType> getExplicitTypeArguments(Arguments arguments) {
-  if (arguments is ArgumentsJudgment) {
+  if (arguments is ArgumentsImpl) {
     if (arguments._explicitTypeArgumentCount == 0) {
       return null;
     } else if (arguments._extensionTypeParameterCount == 0) {
@@ -179,8 +177,52 @@
   ClassInferenceInfo(this.builder);
 }
 
-/// Concrete shadow object representing a set of invocation arguments.
-class ArgumentsJudgment extends Arguments {
+enum InternalExpressionKind {
+  Cascade,
+  CompoundIndexSet,
+  CompoundPropertySet,
+  DeferredCheck,
+  IfNullIndexSet,
+  IfNullPropertySet,
+  IfNullSet,
+  IndexSet,
+  LoadLibraryTearOff,
+  LocalPostIncDec,
+  NullAwareMethodInvocation,
+  NullAwarePropertyGet,
+  NullAwarePropertySet,
+  PropertyPostIncDec,
+  StaticPostIncDec,
+  SuperPostIncDec,
+}
+
+/// Common base class for internal expressions.
+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);
+
+  @override
+  R accept1<R, A>(ExpressionVisitor1<R, A> visitor, A arg) =>
+      visitor.defaultExpression(this, arg);
+
+  @override
+  DartType getStaticType(types) =>
+      unsupported("${runtimeType}.getStaticType", -1, null);
+}
+
+/// Front end specific implementation of [Argument].
+class ArgumentsImpl extends Arguments {
   // TODO(johnniwinther): Move this to the static invocation instead.
   final int _extensionTypeParameterCount;
 
@@ -188,16 +230,14 @@
 
   int _explicitTypeArgumentCount;
 
-  List<Expression> get positionalJudgments => positional.cast();
-
-  ArgumentsJudgment(List<Expression> positional,
+  ArgumentsImpl(List<Expression> positional,
       {List<DartType> types, List<NamedExpression> named})
       : _explicitTypeArgumentCount = types?.length ?? 0,
         _extensionTypeParameterCount = 0,
         _extensionTypeArgumentCount = 0,
         super(positional, types: types, named: named);
 
-  ArgumentsJudgment.forExtensionMethod(int extensionTypeParameterCount,
+  ArgumentsImpl.forExtensionMethod(int extensionTypeParameterCount,
       int typeParameterCount, Expression receiver,
       {List<DartType> extensionTypeArguments = const <DartType>[],
       List<DartType> typeArguments = const <DartType>[],
@@ -227,64 +267,19 @@
   }
 
   static void setNonInferrableArgumentTypes(
-      ArgumentsJudgment arguments, List<DartType> types) {
+      ArgumentsImpl arguments, List<DartType> types) {
     arguments.types.clear();
     arguments.types.addAll(types);
     arguments._explicitTypeArgumentCount = types.length;
   }
 
-  static void removeNonInferrableArgumentTypes(ArgumentsJudgment arguments) {
+  static void removeNonInferrableArgumentTypes(ArgumentsImpl arguments) {
     arguments.types.clear();
     arguments._explicitTypeArgumentCount = 0;
   }
 }
 
-/// Concrete shadow object representing an assert initializer in kernel form.
-class AssertInitializerJudgment extends AssertInitializer
-    implements InitializerJudgment {
-  AssertInitializerJudgment(AssertStatement statement) : super(statement);
-
-  AssertStatementJudgment get judgment => statement;
-
-  @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitAssertInitializerJudgment(this);
-  }
-}
-
-/// Concrete shadow object representing an assertion statement in kernel form.
-class AssertStatementJudgment extends AssertStatement
-    implements StatementJudgment {
-  AssertStatementJudgment(Expression condition,
-      {Expression message, int conditionStartOffset, int conditionEndOffset})
-      : super(condition,
-            message: message,
-            conditionStartOffset: conditionStartOffset,
-            conditionEndOffset: conditionEndOffset);
-
-  Expression get conditionJudgment => condition;
-
-  Expression get messageJudgment => message;
-
-  @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitAssertStatementJudgment(this);
-  }
-}
-
-/// Concrete shadow object representing a statement block in kernel form.
-class BlockJudgment extends Block implements StatementJudgment {
-  BlockJudgment(List<Statement> statements) : super(statements);
-
-  List<Statement> get judgments => statements;
-
-  @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitBlockJudgment(this);
-  }
-}
-
-/// Concrete shadow object representing a cascade expression.
+/// Internal expression representing a cascade expression.
 ///
 /// A cascade expression of the form `a..b()..c()` is represented as the kernel
 /// expression:
@@ -298,32 +293,45 @@
 /// variable"--this is the variable that remembers the value of the expression
 /// preceding the first `..` while the cascades are being evaluated.
 ///
-/// After constructing a [CascadeJudgment], the caller should
+/// 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.
-class CascadeJudgment extends Let implements ExpressionJudgment {
-  DartType inferredType;
+// TODO(johnniwinther): Change the representation to be direct and perform
+// the [Let] encoding in [replace].
+class Cascade extends InternalExpression {
+  VariableDeclaration variable;
 
-  /// Pointer to the last "let" expression in the cascade.
-  Let nextCascade;
+  /// Pointer to the first "let" expression in the cascade, i.e. `e1` in
+  /// `e..e1..e2..e3`;
+  Let _firstCascade;
 
-  /// Creates a [CascadeJudgment] using [variable] as the cascade
+  /// Pointer to the last "let" expression in the cascade, i.e. `e3` in
+  //  /// `e..e1..e2..e3`;
+  Let _lastCascade;
+
+  /// 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.
-  CascadeJudgment(VariableDeclarationJudgment variable)
-      : super(
-            variable,
-            makeLet(new VariableDeclaration.forValue(new _UnfinishedCascade()),
-                new VariableGet(variable))) {
-    nextCascade = body;
+  Cascade(this.variable) {
+    _lastCascade = _firstCascade = makeLet(
+        new VariableDeclaration.forValue(new _UnfinishedCascade()),
+        new VariableGet(variable));
+    variable?.parent = this;
+    _firstCascade.parent = this;
   }
 
-  Expression get targetJudgment => variable.initializer;
+  @override
+  InternalExpressionKind get kind => InternalExpressionKind.Cascade;
 
-  Iterable<Expression> get cascadeJudgments sync* {
-    Let section = body;
+  /// 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;
@@ -334,26 +342,48 @@
   /// 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(nextCascade.variable.initializer is! _UnfinishedCascade);
+    assert(_lastCascade.variable.initializer is! _UnfinishedCascade);
     Let newCascade = makeLet(
         new VariableDeclaration.forValue(new _UnfinishedCascade()),
-        nextCascade.body);
-    nextCascade.body = newCascade;
-    newCascade.parent = nextCascade;
-    nextCascade = newCascade;
+        _lastCascade.body);
+    _lastCascade.body = newCascade;
+    newCascade.parent = _lastCascade;
+    _lastCascade = newCascade;
   }
 
   /// Finalizes the last cascade section with the given [expression].
   void finalize(Expression expression) {
-    assert(nextCascade.variable.initializer is _UnfinishedCascade);
-    nextCascade.variable.initializer = expression;
-    expression.parent = nextCascade.variable;
+    assert(_lastCascade.variable.initializer is _UnfinishedCascade);
+    _lastCascade.variable.initializer = expression;
+    expression.parent = _lastCascade.variable;
   }
 
   @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitCascadeJudgment(this, typeContext);
+  Expression replace() {
+    Expression replacement;
+    parent.replaceChild(
+        this,
+        replacement = new Let(variable, _firstCascade)
+          ..fileOffset = fileOffset);
+    return replacement;
+  }
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    variable?.accept(v);
+    _firstCascade?.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (variable != null) {
+      variable = variable.accept<TreeNode>(v);
+      variable?.parent = this;
+    }
+    if (_firstCascade != null) {
+      _firstCascade = _firstCascade.accept<TreeNode>(v);
+      _firstCascade?.parent = this;
+    }
   }
 }
 
@@ -447,7 +477,7 @@
       FunctionType combinerType =
           inferrer.getFunctionType(combinerTarget, readType, false);
       if (isPreIncDec || isPostIncDec) {
-        rhsType = inferrer.coreTypes.intClass.rawType;
+        rhsType = inferrer.coreTypes.intRawType(inferrer.library.nonNullable);
       } else {
         // It's not necessary to call _storeLetType for [rhs] because the RHS
         // is always passed directly to the combiner; it's never stored in a
@@ -474,8 +504,8 @@
         combinedType = combinerType.returnType;
       }
       MethodContravarianceCheckKind checkKind =
-          inferrer.preCheckInvocationContravariance(read, readType,
-              combinerTarget, combiner, combiner.arguments, combiner);
+          inferrer.preCheckInvocationContravariance(readType, combinerTarget,
+              isThisReceiver: read is ThisExpression);
       Expression replacedCombiner = inferrer.handleInvocationContravariance(
           checkKind,
           combiner,
@@ -522,7 +552,7 @@
     } else {
       _storeLetType(inferrer, write, combinedType);
     }
-    inferredType =
+    DartType inferredType =
         isPostIncDec ? (readType ?? const DynamicType()) : combinedType;
     return new _ComplexAssignmentInferenceResult(
         combinerTarget.member, inferredType);
@@ -553,8 +583,9 @@
 
   DartType _inferReceiver(ShadowTypeInferrer inferrer) {
     if (receiver != null) {
-      inferrer.inferExpression(receiver, const UnknownType(), true);
-      DartType receiverType = getInferredType(receiver, inferrer);
+      DartType receiverType = inferrer
+          .inferExpression(receiver, const UnknownType(), true)
+          .inferredType;
       _storeLetType(inferrer, receiver, receiverType);
       return receiverType;
     } else if (isSuper) {
@@ -566,109 +597,67 @@
   }
 }
 
-/// Concrete shadow object representing a continue statement from a switch
-/// statement, in kernel form.
-class ContinueSwitchJudgment extends ContinueSwitchStatement
-    implements StatementJudgment {
-  ContinueSwitchJudgment(SwitchCase target) : super(target);
+/// Internal expression representing a deferred check.
+// TODO(johnniwinther): Change the representation to be direct and perform
+// the [Let] encoding in [replace].
+class DeferredCheck extends InternalExpression {
+  VariableDeclaration _variable;
+  Expression expression;
 
-  SwitchCaseJudgment get targetJudgment => target;
-
-  @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitContinueSwitchJudgment(this);
+  DeferredCheck(this._variable, this.expression) {
+    _variable?.parent = this;
+    expression?.parent = this;
   }
-}
 
-/// Shadow object representing a deferred check in kernel form.
-class DeferredCheckJudgment extends Let implements ExpressionJudgment {
-  DartType inferredType;
-
-  DeferredCheckJudgment(VariableDeclaration variable, Expression body)
-      : super(variable, body);
-
-  Expression get expression => body;
+  InternalExpressionKind get kind => InternalExpressionKind.DeferredCheck;
 
   @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitDeferredCheckJudgment(this, typeContext);
+  Expression replace() {
+    Expression replacement;
+    parent.replaceChild(this,
+        replacement = new Let(_variable, expression)..fileOffset = fileOffset);
+    return replacement;
   }
-}
-
-/// Concrete shadow object representing a do loop in kernel form.
-class DoJudgment extends DoStatement implements StatementJudgment {
-  DoJudgment(Statement body, Expression condition) : super(body, condition);
-
-  Expression get conditionJudgment => condition;
 
   @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitDoJudgment(this);
+  void visitChildren(Visitor<dynamic> v) {
+    _variable?.accept(v);
+    expression?.accept(v);
   }
-}
-
-/// Concrete shadow object representing a double literal in kernel form.
-class DoubleJudgment extends DoubleLiteral implements ExpressionJudgment {
-  DartType inferredType;
-
-  DoubleJudgment(double value) : super(value);
 
   @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitDoubleJudgment(this, typeContext);
+  void transformChildren(Transformer v) {
+    if (_variable != null) {
+      _variable = _variable.accept<TreeNode>(v);
+      _variable?.parent = this;
+    }
+    if (expression != null) {
+      expression = expression.accept<TreeNode>(v);
+      expression?.parent = this;
+    }
   }
 }
 
 /// Common base class for shadow objects representing expressions in kernel
 /// form.
 abstract class ExpressionJudgment extends Expression {
-  DartType inferredType;
-
   /// Calls back to [inferrer] to perform type inference for whatever concrete
   /// type of [Expression] this is.
   ExpressionInferenceResult acceptInference(
       InferenceVisitor visitor, DartType typeContext);
 }
 
-/// Concrete shadow object representing an empty statement in kernel form.
-class EmptyStatementJudgment extends EmptyStatement
-    implements StatementJudgment {
-  EmptyStatementJudgment();
-
-  @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitEmptyStatementJudgment(this);
-  }
-}
-
-/// Concrete shadow object representing an expression statement in kernel form.
-class ExpressionStatementJudgment extends ExpressionStatement
-    implements StatementJudgment {
-  ExpressionStatementJudgment(Expression expression) : super(expression);
-
-  Expression get judgment => expression;
-
-  @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitExpressionStatementJudgment(this);
-  }
-}
-
 /// Shadow object for [StaticInvocation] when the procedure being invoked is a
 /// factory constructor.
 class FactoryConstructorInvocationJudgment extends StaticInvocation
     implements ExpressionJudgment {
-  DartType inferredType;
+  bool hasBeenInferred = false;
 
   FactoryConstructorInvocationJudgment(
-      Procedure target, ArgumentsJudgment arguments,
+      Procedure target, ArgumentsImpl arguments,
       {bool isConst: false})
       : super(target, arguments, isConst: isConst);
 
-  ArgumentsJudgment get argumentJudgments => arguments;
-
   @override
   ExpressionInferenceResult acceptInference(
       InferenceVisitor visitor, DartType typeContext) {
@@ -676,74 +665,16 @@
   }
 }
 
-/// Concrete shadow object representing a field initializer in kernel form.
-class ShadowFieldInitializer extends FieldInitializer
-    implements InitializerJudgment {
-  ShadowFieldInitializer(Field field, Expression value) : super(field, value);
-
-  @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitShadowFieldInitializer(this);
-  }
-}
-
-/// Concrete shadow object representing a classic for loop in kernel form.
-class ForJudgment extends ForStatement implements StatementJudgment {
-  ForJudgment(List<VariableDeclaration> variables, Expression condition,
-      List<Expression> updates, Statement body)
-      : super(variables ?? [], condition, updates, body);
-
-  Expression get conditionJudgment => condition;
-
-  List<Expression> get updateJudgments => updates.cast();
-
-  @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitForJudgment(this);
-  }
-}
-
-/// Concrete shadow object representing a function expression in kernel form.
-class FunctionNodeJudgment extends FunctionNode {
-  FunctionNodeJudgment(Statement body,
-      {List<TypeParameter> typeParameters,
-      List<VariableDeclaration> positionalParameters,
-      List<VariableDeclaration> namedParameters,
-      int requiredParameterCount,
-      DartType returnType: const DynamicType(),
-      AsyncMarker asyncMarker: AsyncMarker.Sync,
-      AsyncMarker dartAsyncMarker})
-      : super(body,
-            typeParameters: typeParameters,
-            positionalParameters: positionalParameters,
-            namedParameters: namedParameters,
-            requiredParameterCount: requiredParameterCount,
-            returnType: returnType,
-            asyncMarker: asyncMarker,
-            dartAsyncMarker: dartAsyncMarker);
-}
-
-/// Concrete shadow object representing a local function declaration in kernel
-/// form.
-class FunctionDeclarationJudgment extends FunctionDeclaration
-    implements StatementJudgment {
+/// Front end specific implementation of [FunctionDeclaration].
+class FunctionDeclarationImpl extends FunctionDeclaration {
   bool _hasImplicitReturnType = false;
 
-  FunctionDeclarationJudgment(
-      VariableDeclarationJudgment variable, FunctionNodeJudgment function)
+  FunctionDeclarationImpl(
+      VariableDeclarationImpl variable, FunctionNode function)
       : super(variable, function);
 
-  VariableDeclarationJudgment get variableJudgment => variable;
-
-  FunctionNodeJudgment get functionJudgment => function;
-
-  @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitFunctionDeclarationJudgment(this);
-  }
-
   static void setHasImplicitReturnType(
-      FunctionDeclarationJudgment declaration, bool hasImplicitReturnType) {
+      FunctionDeclarationImpl declaration, bool hasImplicitReturnType) {
     declaration._hasImplicitReturnType = hasImplicitReturnType;
   }
 }
@@ -752,7 +683,7 @@
 class InvalidSuperInitializerJudgment extends LocalInitializer
     implements InitializerJudgment {
   final Constructor target;
-  final ArgumentsJudgment argumentsJudgment;
+  final ArgumentsImpl argumentsJudgment;
 
   InvalidSuperInitializerJudgment(
       this.target, this.argumentsJudgment, VariableDeclaration variable)
@@ -771,8 +702,6 @@
 ///
 ///     let v = a in v == null ? b : v
 class IfNullJudgment extends Let implements ExpressionJudgment {
-  DartType inferredType;
-
   IfNullJudgment(VariableDeclaration variable, Expression body)
       : super(variable, body);
 
@@ -780,10 +709,10 @@
   ConditionalExpression get body => super.body;
 
   /// Returns the expression to the left of `??`.
-  Expression get leftJudgment => variable.initializer;
+  Expression get left => variable.initializer;
 
   /// Returns the expression to the right of `??`.
-  Expression get rightJudgment => body.then;
+  Expression get right => body.then;
 
   @override
   ExpressionInferenceResult acceptInference(
@@ -792,19 +721,6 @@
   }
 }
 
-/// Concrete shadow object representing an if statement in kernel form.
-class IfJudgment extends IfStatement implements StatementJudgment {
-  IfJudgment(Expression condition, Statement then, Statement otherwise)
-      : super(condition, then, otherwise);
-
-  Expression get conditionJudgment => condition;
-
-  @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitIfJudgment(this);
-  }
-}
-
 /// Concrete shadow object representing an assignment to a target for which
 /// assignment is not allowed.
 class IllegalAssignmentJudgment extends ComplexAssignmentJudgment {
@@ -892,7 +808,6 @@
 
 /// Concrete shadow object representing an integer literal in kernel form.
 class IntJudgment extends IntLiteral implements ExpressionJudgment {
-  DartType inferredType;
   final String literal;
 
   IntJudgment(int value, this.literal) : super(value);
@@ -916,8 +831,6 @@
   final int fileOffset;
   bool isParenthesized = false;
 
-  DartType inferredType;
-
   ShadowLargeIntLiteral(this.literal, this.fileOffset) : super(0);
 
   double asDouble({bool negated: false}) {
@@ -965,86 +878,21 @@
     value?.parent = this;
   }
 
-  Expression get judgment => value;
-
   @override
   void acceptInference(InferenceVisitor visitor) {
     return visitor.visitShadowInvalidFieldInitializer(this);
   }
 }
 
-/// Type inference derivation for [ListLiteral].
-class ListLiteralJudgment extends ListLiteral implements ExpressionJudgment {
-  DartType inferredType;
-
-  ListLiteralJudgment(List<Expression> expressions,
-      {DartType typeArgument, bool isConst: false})
-      : assert(typeArgument != null),
-        super(expressions, typeArgument: typeArgument, isConst: isConst);
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitListLiteralJudgment(this, typeContext);
-  }
-}
-
-/// Type inference derivation for [SetLiteral].
-class SetLiteralJudgment extends SetLiteral implements ExpressionJudgment {
-  DartType inferredType;
-
-  SetLiteralJudgment(List<Expression> expressions,
-      {DartType typeArgument, bool isConst: false})
-      : assert(typeArgument != null),
-        super(expressions, typeArgument: typeArgument, isConst: isConst);
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitSetLiteralJudgment(this, typeContext);
-  }
-}
-
-/// Type inference derivation for [MapLiteral].
-class MapLiteralJudgment extends MapLiteral implements ExpressionJudgment {
-  DartType inferredType;
-
-  MapLiteralJudgment(List<MapEntry> judgments,
-      {DartType keyType, DartType valueType, bool isConst: false})
-      : assert(keyType != null),
-        assert(valueType != null),
-        super(judgments,
-            keyType: keyType, valueType: valueType, isConst: isConst);
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitMapLiteralJudgment(this, typeContext);
-  }
-}
-
-/// Shadow object for [MethodInvocation].
-class MethodInvocationJudgment extends MethodInvocation
-    implements ExpressionJudgment {
-  DartType inferredType;
-
+/// Front end specific implementation of [MethodInvocation].
+class MethodInvocationImpl extends MethodInvocation {
   /// Indicates whether this method invocation is a call to a `call` method
   /// resulting from the invocation of a function expression.
-  final bool _isImplicitCall;
+  final bool isImplicitCall;
 
-  MethodInvocationJudgment(
-      Expression receiver, Name name, ArgumentsJudgment arguments,
-      {bool isImplicitCall: false, Member interfaceTarget})
-      : _isImplicitCall = isImplicitCall,
-        super(receiver, name, arguments, interfaceTarget);
-
-  ArgumentsJudgment get argumentJudgments => arguments;
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitMethodInvocationJudgment(this, typeContext);
-  }
+  MethodInvocationImpl(Expression receiver, Name name, ArgumentsImpl arguments,
+      {this.isImplicitCall: false, Member interfaceTarget})
+      : super(receiver, name, arguments, interfaceTarget);
 }
 
 /// Concrete shadow object representing a named function expression.
@@ -1058,13 +906,9 @@
 ///     let f = () { ... } in f
 class NamedFunctionExpressionJudgment extends Let
     implements ExpressionJudgment {
-  DartType inferredType;
-
-  NamedFunctionExpressionJudgment(VariableDeclarationJudgment variable)
+  NamedFunctionExpressionJudgment(VariableDeclarationImpl variable)
       : super(variable, new VariableGet(variable));
 
-  VariableDeclarationJudgment get variableJudgment => variable;
-
   @override
   ExpressionInferenceResult acceptInference(
       InferenceVisitor visitor, DartType typeContext) {
@@ -1072,56 +916,126 @@
   }
 }
 
-/// Concrete shadow object representing a null-aware method invocation.
+/// Internal expression representing a null-aware method invocation.
 ///
-/// A null-aware method invocation of the form `a?.b(...)` is represented as the
-/// expression:
+/// A null-aware method invocation of the form `a?.b(...)` is encoded as:
 ///
 ///     let v = a in v == null ? null : v.b(...)
-class NullAwareMethodInvocationJudgment extends Let
-    implements ExpressionJudgment {
-  DartType inferredType;
+///
+class NullAwareMethodInvocation extends InternalExpression {
+  /// The synthetic variable whose initializer hold the receiver.
+  VariableDeclaration variable;
 
-  NullAwareMethodInvocationJudgment(
-      VariableDeclaration variable, Expression body)
-      : super(variable, body);
+  /// The expression that invokes the method on [variable].
+  Expression invocation;
+
+  NullAwareMethodInvocation(this.variable, this.invocation) {
+    variable?.parent = this;
+    invocation?.parent = this;
+  }
 
   @override
-  ConditionalExpression get body => super.body;
-
-  MethodInvocation get _desugaredInvocation => body.otherwise;
+  InternalExpressionKind get kind =>
+      InternalExpressionKind.NullAwareMethodInvocation;
 
   @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitNullAwareMethodInvocationJudgment(this, typeContext);
+  void visitChildren(Visitor<dynamic> v) {
+    variable?.accept(v);
+    invocation?.accept(v);
+  }
+
+  @override
+  transformChildren(Transformer v) {
+    if (variable != null) {
+      variable = variable.accept<TreeNode>(v);
+      variable?.parent = this;
+    }
+    if (invocation != null) {
+      invocation = invocation.accept<TreeNode>(v);
+      invocation?.parent = this;
+    }
   }
 }
 
-/// Concrete shadow object representing a null-aware read from a property.
+/// Internal expression representing a null-aware read from a property.
 ///
-/// A null-aware property get of the form `a?.b` is represented as the kernel
-/// expression:
+/// A null-aware property get of the form `a?.b` is encoded as:
 ///
 ///     let v = a in v == null ? null : v.b
-class NullAwarePropertyGetJudgment extends Let implements ExpressionJudgment {
-  DartType inferredType;
+///
+class NullAwarePropertyGet extends InternalExpression {
+  /// The synthetic variable whose initializer hold the receiver.
+  VariableDeclaration variable;
 
-  NullAwarePropertyGetJudgment(
-      VariableDeclaration variable, ConditionalExpression body)
-      : super(variable, body);
+  /// The expression that reads the property from [variable].
+  Expression read;
+
+  NullAwarePropertyGet(this.variable, this.read) {
+    variable?.parent = this;
+    read?.parent = this;
+  }
 
   @override
-  ConditionalExpression get body => super.body;
-
-  PropertyGet get _desugaredGet => body.otherwise;
-
-  Expression get receiverJudgment => variable.initializer;
+  InternalExpressionKind get kind =>
+      InternalExpressionKind.NullAwarePropertyGet;
 
   @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitNullAwarePropertyGetJudgment(this, typeContext);
+  void visitChildren(Visitor<dynamic> v) {
+    variable?.accept(v);
+    read?.accept(v);
+  }
+
+  @override
+  transformChildren(Transformer v) {
+    if (variable != null) {
+      variable = variable.accept<TreeNode>(v);
+      variable?.parent = this;
+    }
+    if (read != null) {
+      read = read.accept<TreeNode>(v);
+      read?.parent = this;
+    }
+  }
+}
+
+/// Internal expression representing a null-aware read from a property.
+///
+/// A null-aware property get of the form `a?.b = c` is encoded as:
+///
+///     let v = a in v == null ? null : v.b = c
+///
+class NullAwarePropertySet extends InternalExpression {
+  /// The synthetic variable whose initializer hold the receiver.
+  VariableDeclaration variable;
+
+  /// The expression that writes the value to the property in [variable].
+  Expression write;
+
+  NullAwarePropertySet(this.variable, this.write) {
+    variable?.parent = this;
+    write?.parent = this;
+  }
+
+  @override
+  InternalExpressionKind get kind =>
+      InternalExpressionKind.NullAwarePropertySet;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    variable?.accept(v);
+    write?.accept(v);
+  }
+
+  @override
+  transformChildren(Transformer v) {
+    if (variable != null) {
+      variable = variable.accept<TreeNode>(v);
+      variable?.parent = this;
+    }
+    if (write != null) {
+      write = write.accept<TreeNode>(v);
+      write?.parent = this;
+    }
   }
 }
 
@@ -1154,42 +1068,12 @@
   }
 }
 
-/// Concrete shadow object representing a redirecting initializer in kernel
-/// form.
-class RedirectingInitializerJudgment extends RedirectingInitializer
-    implements InitializerJudgment {
-  RedirectingInitializerJudgment(
-      Constructor target, ArgumentsJudgment arguments)
-      : super(target, arguments);
-
-  ArgumentsJudgment get argumentJudgments => arguments;
-
-  @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitRedirectingInitializerJudgment(this);
-  }
-}
-
-/// Concrete shadow object representing a return statement in kernel form.
-class ReturnJudgment extends ReturnStatement implements StatementJudgment {
+/// Front end specific implementation of [ReturnStatement].
+class ReturnStatementImpl extends ReturnStatement {
   final bool isArrow;
 
-  ReturnJudgment(this.isArrow, [Expression expression]) : super(expression);
-
-  Expression get judgment => expression;
-
-  @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitReturnJudgment(this);
-  }
-}
-
-/// Common base class for shadow objects representing statements in kernel
-/// form.
-abstract class StatementJudgment extends Statement {
-  /// Calls back to [inferrer] to perform type inference for whatever concrete
-  /// type of [StatementJudgment] this is.
-  void acceptInference(InferenceVisitor visitor);
+  ReturnStatementImpl(this.isArrow, [Expression expression])
+      : super(expression);
 }
 
 /// Concrete shadow object representing an assignment to a static variable.
@@ -1203,97 +1087,6 @@
   }
 }
 
-/// Concrete shadow object representing a super initializer in kernel form.
-class SuperInitializerJudgment extends SuperInitializer
-    implements InitializerJudgment {
-  SuperInitializerJudgment(Constructor target, ArgumentsJudgment arguments)
-      : super(target, arguments);
-
-  ArgumentsJudgment get argumentJudgments => arguments;
-
-  @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitSuperInitializerJudgment(this);
-  }
-}
-
-/// Shadow object for [SuperMethodInvocation].
-class SuperMethodInvocationJudgment extends SuperMethodInvocation
-    implements ExpressionJudgment {
-  DartType inferredType;
-
-  SuperMethodInvocationJudgment(Name name, ArgumentsJudgment arguments,
-      {Procedure interfaceTarget})
-      : super(name, arguments, interfaceTarget);
-
-  ArgumentsJudgment get argumentJudgments => arguments;
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitSuperMethodInvocationJudgment(this, typeContext);
-  }
-}
-
-/// Shadow object for [SuperPropertyGet].
-class SuperPropertyGetJudgment extends SuperPropertyGet
-    implements ExpressionJudgment {
-  DartType inferredType;
-
-  SuperPropertyGetJudgment(Name name, {Member interfaceTarget})
-      : super(name, interfaceTarget);
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitSuperPropertyGetJudgment(this, typeContext);
-  }
-}
-
-/// Concrete shadow object representing a switch case.
-class SwitchCaseJudgment extends SwitchCase {
-  SwitchCaseJudgment(
-      List<Expression> expressions, List<int> expressionOffsets, Statement body,
-      {bool isDefault: false})
-      : super(expressions, expressionOffsets, body, isDefault: isDefault);
-
-  SwitchCaseJudgment.defaultCase(Statement body) : super.defaultCase(body);
-
-  SwitchCaseJudgment.empty() : super.empty();
-
-  List<Expression> get expressionJudgments => expressions.cast();
-}
-
-/// Concrete shadow object representing a switch statement in kernel form.
-class SwitchStatementJudgment extends SwitchStatement
-    implements StatementJudgment {
-  SwitchStatementJudgment(Expression expression, List<SwitchCase> cases)
-      : super(expression, cases);
-
-  Expression get expressionJudgment => expression;
-
-  List<SwitchCaseJudgment> get caseJudgments => cases.cast();
-
-  @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitSwitchStatementJudgment(this);
-  }
-}
-
-/// Shadow object for [SymbolLiteral].
-class SymbolLiteralJudgment extends SymbolLiteral
-    implements ExpressionJudgment {
-  DartType inferredType;
-
-  SymbolLiteralJudgment(String value) : super(value);
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitSymbolLiteralJudgment(this, typeContext);
-  }
-}
-
 /// Synthetic judgment class representing an attempt to invoke an unresolved
 /// constructor, or a constructor that cannot be invoked, or a resolved
 /// constructor with wrong number of arguments.
@@ -1303,11 +1096,9 @@
   final Arguments arguments;
 
   InvalidConstructorInvocationJudgment._(
-      kernel.Expression desugared, this.constructor, this.arguments)
+      Expression desugared, this.constructor, this.arguments)
       : super._(desugared);
 
-  ArgumentsJudgment get argumentJudgments => arguments;
-
   @override
   ExpressionInferenceResult acceptInference(
       InferenceVisitor visitor, DartType typeContext) {
@@ -1320,7 +1111,7 @@
 class InvalidWriteJudgment extends SyntheticExpressionJudgment {
   final Expression expression;
 
-  InvalidWriteJudgment._(kernel.Expression desugared, this.expression)
+  InvalidWriteJudgment._(Expression desugared, this.expression)
       : super._(desugared);
 
   @override
@@ -1336,8 +1127,6 @@
 /// These expressions are removed by type inference and replaced with their
 /// desugared equivalents.
 class SyntheticExpressionJudgment extends Let implements ExpressionJudgment {
-  DartType inferredType;
-
   SyntheticExpressionJudgment._(Expression desugared)
       : super(new VariableDeclaration('_', initializer: new NullLiteral()),
             desugared);
@@ -1359,9 +1148,16 @@
   /// Removes this expression from the expression tree, replacing it with
   /// [desugared].
   Expression _replaceWithDesugared() {
-    parent.replaceChild(this, desugared);
+    Expression replacement = desugared;
+    if (replacement is InternalExpression) {
+      // This is needed because some (StaticAssignmentJudgment at least) do
+      // not visit their desugared expression during inference.
+      InternalExpression internalExpression = replacement;
+      replacement = internalExpression.replace();
+    }
+    parent.replaceChild(this, replacement);
     parent = null;
-    return desugared;
+    return replacement;
   }
 
   /// Updates any [Let] nodes in the desugared expression to account for the
@@ -1400,51 +1196,17 @@
     // lead to exceptions during transformations, but we have to accept a
     // [Transformer] as this is used to implement `replaceChild`.
     if (v is Transformer) return super.accept(v);
-    throw unsupported("accept", fileOffset, getFileUri(this));
+    throw unsupported("${runtimeType}.accept", fileOffset, getFileUri(this));
   }
 
   @override
   R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) {
-    throw unsupported("accept1", fileOffset, getFileUri(this));
+    throw unsupported("${runtimeType}.accept1", fileOffset, getFileUri(this));
   }
 
   @override
   visitChildren(Visitor<dynamic> v) {
-    unsupported("visitChildren", fileOffset, getFileUri(this));
-  }
-}
-
-/// Concrete shadow object representing a catch clause.
-class CatchJudgment extends Catch {
-  CatchJudgment(VariableDeclaration exception, Statement body,
-      {DartType guard: const DynamicType(), VariableDeclaration stackTrace})
-      : super(exception, body, guard: guard, stackTrace: stackTrace);
-
-  VariableDeclarationJudgment get exceptionJudgment => exception;
-
-  VariableDeclarationJudgment get stackTraceJudgment => stackTrace;
-}
-
-/// Concrete shadow object representing a try-catch block in kernel form.
-class TryCatchJudgment extends TryCatch implements StatementJudgment {
-  TryCatchJudgment(Statement body, List<Catch> catches) : super(body, catches);
-
-  List<CatchJudgment> get catchJudgments => catches.cast();
-
-  @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitTryCatchJudgment(this);
-  }
-}
-
-/// Concrete shadow object representing a try-finally block in kernel form.
-class TryFinallyJudgment extends TryFinally implements StatementJudgment {
-  TryFinallyJudgment(Statement body, Statement finalizer)
-      : super(body, finalizer);
-
-  @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitTryFinallyJudgment(this);
+    unsupported("${runtimeType}.visitChildren", fileOffset, getFileUri(this));
   }
 }
 
@@ -1485,7 +1247,7 @@
 
   @override
   ExpressionInferenceResult inferExpression(
-      kernel.Expression expression, DartType typeContext, bool typeNeeded,
+      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.
@@ -1515,7 +1277,7 @@
     DartType inferredType = result.inferredType;
     assert(inferredType != null, "No type inferred for $expression.");
     if (inferredType is VoidType && !isVoidAllowed) {
-      if (expression.parent is! ArgumentsJudgment) {
+      if (expression.parent is! ArgumentsImpl) {
         helper?.addProblem(
             messageVoidExpression, expression.fileOffset, noLength);
       }
@@ -1524,17 +1286,18 @@
   }
 
   @override
-  void inferInitializer(
-      InferenceHelper helper, kernel.Initializer initializer) {
-    assert(initializer is InitializerJudgment);
+  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).
-    InitializerJudgment kernelInitializer = initializer;
-    kernelInitializer.acceptInference(new InferenceVisitor(this));
+    if (initializer is InitializerJudgment) {
+      initializer.acceptInference(new InferenceVisitor(this));
+    } else {
+      initializer.accept(new InferenceVisitor(this));
+    }
     this.helper = null;
   }
 
@@ -1543,41 +1306,12 @@
     // 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 is StatementJudgment) {
-      // Use polymorphic dispatch on [KernelStatement] to perform whatever kind
-      // of type inference is correct for this kind of statement.
-      // 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).
-      return statement.acceptInference(new InferenceVisitor(this));
-    } else if (statement is ForInStatement) {
-      return statement.accept1(new InferenceVisitor(this), null);
-    } else if (statement is LabeledStatement) {
-      return statement.accept1(new InferenceVisitor(this), null);
-    } else if (statement is BreakStatement) {
-      return statement.accept1(new InferenceVisitor(this), null);
-    } else {
-      // Encountered a statement type for which type inference is not yet
-      // implemented, so just skip it for now.
-      // TODO(paulberry): once the BodyBuilder uses shadow classes for
-      // everything, this case should no longer be needed.
+    if (statement != null) {
+      statement.accept(new InferenceVisitor(this));
     }
   }
 }
 
-class TypeLiteralJudgment extends TypeLiteral implements ExpressionJudgment {
-  DartType inferredType;
-
-  TypeLiteralJudgment(DartType type) : super(type);
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitTypeLiteralJudgment(this, typeContext);
-  }
-}
-
 /// Concrete implementation of [TypePromoter] specialized to work with kernel
 /// objects.
 class ShadowTypePromoter extends TypePromoterImpl {
@@ -1586,7 +1320,7 @@
 
   @override
   int getVariableFunctionNestingLevel(VariableDeclaration variable) {
-    if (variable is VariableDeclarationJudgment) {
+    if (variable is VariableDeclarationImpl) {
       return variable._functionNestingLevel;
     } else {
       // Hack to deal with the fact that BodyBuilder still creates raw
@@ -1599,8 +1333,8 @@
 
   @override
   bool isPromotionCandidate(VariableDeclaration variable) {
-    assert(variable is VariableDeclarationJudgment);
-    VariableDeclarationJudgment kernelVariableDeclaration = variable;
+    assert(variable is VariableDeclarationImpl);
+    VariableDeclarationImpl kernelVariableDeclaration = variable;
     return !kernelVariableDeclaration._isLocalFunction;
   }
 
@@ -1611,7 +1345,7 @@
 
   @override
   void setVariableMutatedAnywhere(VariableDeclaration variable) {
-    if (variable is VariableDeclarationJudgment) {
+    if (variable is VariableDeclarationImpl) {
       variable._mutatedAnywhere = true;
     } else {
       // Hack to deal with the fact that BodyBuilder still creates raw
@@ -1623,7 +1357,7 @@
 
   @override
   void setVariableMutatedInClosure(VariableDeclaration variable) {
-    if (variable is VariableDeclarationJudgment) {
+    if (variable is VariableDeclarationImpl) {
       variable._mutatedInClosure = true;
     } else {
       // Hack to deal with the fact that BodyBuilder still creates raw
@@ -1635,7 +1369,7 @@
 
   @override
   bool wasVariableMutatedAnywhere(VariableDeclaration variable) {
-    if (variable is VariableDeclarationJudgment) {
+    if (variable is VariableDeclarationImpl) {
       return variable._mutatedAnywhere;
     } else {
       // Hack to deal with the fact that BodyBuilder still creates raw
@@ -1657,9 +1391,8 @@
   }
 }
 
-/// Concrete shadow object representing a variable declaration in kernel form.
-class VariableDeclarationJudgment extends VariableDeclaration
-    implements StatementJudgment {
+/// Front end specific implementation of [VariableDeclaration].
+class VariableDeclarationImpl extends VariableDeclaration {
   final bool forSyntheticToken;
 
   final bool _implicitlyTyped;
@@ -1680,7 +1413,7 @@
   // TODO(ahe): Investigate if this can be removed.
   final bool _isLocalFunction;
 
-  VariableDeclarationJudgment(String name, this._functionNestingLevel,
+  VariableDeclarationImpl(String name, this._functionNestingLevel,
       {this.forSyntheticToken: false,
       Expression initializer,
       DartType type,
@@ -1703,51 +1436,44 @@
             isLate: isLate,
             isRequired: isRequired);
 
-  VariableDeclarationJudgment.forEffect(
-      Expression initializer, this._functionNestingLevel)
+  VariableDeclarationImpl.forEffect(Expression initializer)
       : forSyntheticToken = false,
+        _functionNestingLevel = 0,
         _implicitlyTyped = false,
         _isLocalFunction = false,
         super.forValue(initializer);
 
-  VariableDeclarationJudgment.forValue(Expression initializer)
+  VariableDeclarationImpl.forValue(Expression initializer)
       : forSyntheticToken = false,
         _functionNestingLevel = 0,
         _implicitlyTyped = true,
         _isLocalFunction = false,
         super.forValue(initializer);
 
-  Expression get initializerJudgment => initializer;
-
-  @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitVariableDeclarationJudgment(this);
-  }
-
-  /// Determine whether the given [VariableDeclarationJudgment] had an implicit
+  /// Determine whether the given [VariableDeclarationImpl] had an implicit
   /// type.
   ///
   /// This is static to avoid introducing a method that would be visible to
   /// the kernel.
-  static bool isImplicitlyTyped(VariableDeclarationJudgment variable) =>
+  static bool isImplicitlyTyped(VariableDeclarationImpl variable) =>
       variable._implicitlyTyped;
 
-  /// Determines whether the given [VariableDeclarationJudgment] represents a
+  /// Determines whether the given [VariableDeclarationImpl] represents a
   /// local function.
   ///
   /// This is static to avoid introducing a method that would be visible to the
   /// kernel.
-  static bool isLocalFunction(VariableDeclarationJudgment variable) =>
+  static bool isLocalFunction(VariableDeclarationImpl variable) =>
       variable._isLocalFunction;
 }
 
 /// Synthetic judgment class representing an attempt to invoke an unresolved
 /// target.
 class UnresolvedTargetInvocationJudgment extends SyntheticExpressionJudgment {
-  final ArgumentsJudgment argumentsJudgment;
+  final ArgumentsImpl argumentsJudgment;
 
   UnresolvedTargetInvocationJudgment._(
-      kernel.Expression desugared, this.argumentsJudgment)
+      Expression desugared, this.argumentsJudgment)
       : super._(desugared);
 
   @override
@@ -1764,7 +1490,7 @@
   final Expression rhs;
 
   UnresolvedVariableAssignmentJudgment._(
-      kernel.Expression desugared, this.isCompound, this.rhs)
+      Expression desugared, this.isCompound, this.rhs)
       : super._(desugared);
 
   @override
@@ -1774,79 +1500,55 @@
   }
 }
 
-/// Concrete shadow object representing a read from a variable in kernel form.
-class VariableGetJudgment extends VariableGet implements ExpressionJudgment {
-  DartType inferredType;
-
+/// Front end specific implementation of [VariableGet].
+class VariableGetImpl extends VariableGet {
   final TypePromotionFact _fact;
 
   final TypePromotionScope _scope;
 
-  VariableGetJudgment(VariableDeclaration variable, this._fact, this._scope)
+  VariableGetImpl(VariableDeclaration variable, this._fact, this._scope)
       : super(variable);
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitVariableGetJudgment(this, typeContext);
-  }
 }
 
-/// Concrete shadow object representing a while loop in kernel form.
-class WhileJudgment extends WhileStatement implements StatementJudgment {
-  WhileJudgment(Expression condition, Statement body) : super(condition, body);
-
-  Expression get conditionJudgment => condition;
-
-  @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitWhileJudgment(this);
-  }
-}
-
-/// Concrete shadow object representing a yield statement in kernel form.
-class YieldJudgment extends YieldStatement implements StatementJudgment {
-  YieldJudgment(bool isYieldStar, Expression expression)
-      : super(expression, isYieldStar: isYieldStar);
-
-  Expression get judgment => expression;
-
-  @override
-  void acceptInference(InferenceVisitor visitor) {
-    return visitor.visitYieldJudgment(this);
-  }
-}
-
-/// Concrete shadow object representing a deferred load library call.
-class LoadLibraryJudgment extends LoadLibrary implements ExpressionJudgment {
+/// Front end specific implementation of [LoadLibrary].
+class LoadLibraryImpl extends LoadLibrary {
   final Arguments arguments;
 
-  DartType inferredType;
-
-  LoadLibraryJudgment(LibraryDependency import, this.arguments) : super(import);
-
-  ArgumentsJudgment get argumentJudgments => arguments;
-
-  @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitLoadLibraryJudgment(this, typeContext);
-  }
+  LoadLibraryImpl(LibraryDependency import, this.arguments) : super(import);
 }
 
-/// Concrete shadow object representing a tear-off of a `loadLibrary` function.
-class LoadLibraryTearOffJudgment extends StaticGet
-    implements ExpressionJudgment {
-  final LibraryDependency import;
+/// Internal expression representing a tear-off of a `loadLibrary` function.
+class LoadLibraryTearOff extends InternalExpression {
+  LibraryDependency import;
+  Procedure target;
 
-  DartType inferredType;
-
-  LoadLibraryTearOffJudgment(this.import, Procedure target) : super(target);
+  LoadLibraryTearOff(this.import, this.target);
 
   @override
-  ExpressionInferenceResult acceptInference(
-      InferenceVisitor visitor, DartType typeContext) {
-    return visitor.visitLoadLibraryTearOffJudgment(this, typeContext);
+  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);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (import != null) {
+      import = import.accept<TreeNode>(v);
+    }
+    if (target != null) {
+      target = target.accept<TreeNode>(v);
+    }
   }
 }
 
@@ -1867,11 +1569,11 @@
 
   R accept1<R, A>(v, arg) => unsupported("accept1", -1, null);
 
-  getStaticType(types) => unsupported("getStaticType", -1, null);
+  DartType getStaticType(types) => unsupported("getStaticType", -1, null);
 
-  transformChildren(v) => unsupported("transformChildren", -1, null);
+  void transformChildren(v) => unsupported("transformChildren", -1, null);
 
-  visitChildren(v) => unsupported("visitChildren", -1, null);
+  void visitChildren(v) => unsupported("visitChildren", -1, null);
 }
 
 class SyntheticWrapper {
@@ -1890,7 +1592,7 @@
   }
 
   static Expression wrapInvalidConstructorInvocation(
-      kernel.Expression desugared, Member constructor, Arguments arguments) {
+      Expression desugared, Member constructor, Arguments arguments) {
     return new InvalidConstructorInvocationJudgment._(
         desugared, constructor, arguments)
       ..fileOffset = desugared.fileOffset;
@@ -1934,3 +1636,620 @@
     return new VariableAssignmentJudgment._(rhs)..fileOffset = rhs.fileOffset;
   }
 }
+
+/// Internal expression representing an if-null property set.
+///
+/// An if-null property set of the form `o.a ??= b` is, if used for value,
+/// encoded as the expression:
+///
+///     let v1 = o in let v2 = v1.a in v2 == null ? v1.a = b : v2
+///
+/// and, if used for effect, encoded as the expression:
+///
+///     let v1 = o in v1.a == null ? v1.a = b : null
+///
+class IfNullPropertySet extends InternalExpression {
+  /// The synthetic variable whose initializer hold the receiver.
+  VariableDeclaration variable;
+
+  /// The expression that reads the property from [variable].
+  Expression read;
+
+  /// The expression that writes the value to the property on [variable].
+  Expression write;
+
+  /// If `true`, the expression is only need for effect and not for its value.
+  final bool forEffect;
+
+  IfNullPropertySet(this.variable, this.read, this.write, {this.forEffect})
+      : assert(forEffect != null) {
+    variable?.parent = this;
+    read?.parent = this;
+    write?.parent = this;
+  }
+
+  @override
+  InternalExpressionKind get kind => InternalExpressionKind.IfNullPropertySet;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    variable?.accept(v);
+    read?.accept(v);
+    write?.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (variable != null) {
+      variable = variable.accept<TreeNode>(v);
+      variable?.parent = this;
+    }
+    if (read != null) {
+      read = read.accept<TreeNode>(v);
+      read?.parent = this;
+    }
+    if (write != null) {
+      write = write.accept<TreeNode>(v);
+      write?.parent = this;
+    }
+  }
+}
+
+/// Internal expression representing an if-null assignment.
+///
+/// An if-null assignment of the form `a ??= b` is, if used for value,
+/// encoded as the expression:
+///
+///     let v1 = a in v1 == null ? a = b : v1
+///
+/// and, if used for effect, encoded as the expression:
+///
+///     a == null ? a = b : null
+///
+class IfNullSet extends InternalExpression {
+  /// The expression that reads the property from [variable].
+  Expression read;
+
+  /// The expression that writes the value to the property on [variable].
+  Expression write;
+
+  /// If `true`, the expression is only need for effect and not for its value.
+  final bool forEffect;
+
+  IfNullSet(this.read, this.write, {this.forEffect})
+      : assert(forEffect != null) {
+    read?.parent = this;
+    write?.parent = this;
+  }
+
+  @override
+  InternalExpressionKind get kind => InternalExpressionKind.IfNullSet;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    read?.accept(v);
+    write?.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (read != null) {
+      read = read.accept<TreeNode>(v);
+      read?.parent = this;
+    }
+    if (write != null) {
+      write = write.accept<TreeNode>(v);
+      write?.parent = this;
+    }
+  }
+}
+
+/// Internal expression representing an compound property assignment.
+///
+/// An compound property assignment of the form `o.a += b` is encoded as the
+/// expression:
+///
+///     let v1 = o in v1.a = v1.a + b
+///
+class CompoundPropertySet extends InternalExpression {
+  /// The synthetic variable whose initializer hold the receiver.
+  VariableDeclaration variable;
+
+  /// The expression that writes the result of the binary operation to the
+  /// property on [variable].
+  Expression write;
+
+  CompoundPropertySet(this.variable, this.write) {
+    variable?.parent = this;
+    write?.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);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (variable != null) {
+      variable = variable.accept<TreeNode>(v);
+      variable?.parent = this;
+    }
+    if (write != null) {
+      write = write.accept<TreeNode>(v);
+      write?.parent = this;
+    }
+  }
+}
+
+/// Internal expression representing an compound property assignment.
+///
+/// An compound property assignment of the form `o.a++` is encoded as the
+/// expression:
+///
+///     let v1 = o in let v2 = v1.a in let v3 = v1.a = v2 + 1 in v2
+///
+class PropertyPostIncDec extends InternalExpression {
+  /// The synthetic variable whose initializer hold the receiver.
+  VariableDeclaration variable;
+
+  /// The expression that reads the property on [variable].
+  VariableDeclaration read;
+
+  /// The expression that writes the result of the binary operation to the
+  /// property on [variable].
+  VariableDeclaration write;
+
+  PropertyPostIncDec(this.variable, this.read, this.write) {
+    variable?.parent = this;
+    read?.parent = this;
+    write?.parent = this;
+  }
+
+  @override
+  InternalExpressionKind get kind => InternalExpressionKind.PropertyPostIncDec;
+
+  @override
+  Expression replace() {
+    Expression replacement;
+    replaceWith(replacement = new Let(
+        variable, createLet(read, createLet(write, createVariableGet(read))))
+      ..fileOffset = fileOffset);
+    return replacement;
+  }
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    variable?.accept(v);
+    read?.accept(v);
+    write?.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (variable != null) {
+      variable = variable.accept<TreeNode>(v);
+      variable?.parent = this;
+    }
+    if (write != null) {
+      write = write.accept<TreeNode>(v);
+      write?.parent = this;
+    }
+  }
+}
+
+/// Internal expression representing an local variable post inc/dec expression.
+///
+/// An local variable post inc/dec expression of the form `a++` is encoded as
+/// the expression:
+///
+///     let v1 = a in let v2 = a = v1 + 1 in v1
+///
+class LocalPostIncDec extends InternalExpression {
+  /// The expression that reads the local variable.
+  VariableDeclaration read;
+
+  /// The expression that writes the result of the binary operation to the
+  /// local variable.
+  VariableDeclaration write;
+
+  LocalPostIncDec(this.read, this.write) {
+    read?.parent = this;
+    write?.parent = this;
+  }
+
+  @override
+  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);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (read != null) {
+      read = read.accept<TreeNode>(v);
+      read?.parent = this;
+    }
+    if (write != null) {
+      write = write.accept<TreeNode>(v);
+      write?.parent = this;
+    }
+  }
+}
+
+/// Internal expression representing an static member post inc/dec expression.
+///
+/// An local variable post inc/dec expression of the form `a++` is encoded as
+/// the expression:
+///
+///     let v1 = a in let v2 = a = v1 + 1 in v1
+///
+class StaticPostIncDec extends InternalExpression {
+  /// The expression that reads the static member.
+  VariableDeclaration read;
+
+  /// The expression that writes the result of the binary operation to the
+  /// static member.
+  VariableDeclaration write;
+
+  StaticPostIncDec(this.read, this.write) {
+    read?.parent = this;
+    write?.parent = this;
+  }
+
+  @override
+  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);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (read != null) {
+      read = read.accept<TreeNode>(v);
+      read?.parent = this;
+    }
+    if (write != null) {
+      write = write.accept<TreeNode>(v);
+      write?.parent = this;
+    }
+  }
+}
+
+/// Internal expression representing an static member post inc/dec expression.
+///
+/// An local variable post inc/dec expression of the form `super.a++` is encoded
+/// as the expression:
+///
+///     let v1 = super.a in let v2 = super.a = v1 + 1 in v1
+///
+class SuperPostIncDec extends InternalExpression {
+  /// The expression that reads the static member.
+  VariableDeclaration read;
+
+  /// The expression that writes the result of the binary operation to the
+  /// static member.
+  VariableDeclaration write;
+
+  SuperPostIncDec(this.read, this.write) {
+    read?.parent = this;
+    write?.parent = this;
+  }
+
+  @override
+  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);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (read != null) {
+      read = read.accept<TreeNode>(v);
+      read?.parent = this;
+    }
+    if (write != null) {
+      write = write.accept<TreeNode>(v);
+      write?.parent = this;
+    }
+  }
+}
+
+/// Internal expression representing an index set expression.
+///
+/// An index set expression of the form `o[a] = b` used for value is encoded as
+/// the expression:
+///
+///     let v1 = o in let v2 = a in let v3 = b in let _ = o.[]=(v2, v3) in v3
+///
+/// An index set expression used for effect is encoded as
+///
+///    o.[]=(a, b)
+///
+/// using [MethodInvocationImpl].
+///
+class IndexSet extends InternalExpression {
+  /// The receiver on which the index set operation is performed.
+  Expression receiver;
+
+  /// The index expression of the operation.
+  Expression index;
+
+  /// The value expression of the operation.
+  Expression value;
+
+  IndexSet(this.receiver, this.index, this.value) {
+    receiver?.parent = this;
+    index?.parent = this;
+    value?.parent = this;
+  }
+
+  @override
+  InternalExpressionKind get kind => InternalExpressionKind.IndexSet;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    receiver?.accept(v);
+    index?.accept(v);
+    value?.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (receiver != null) {
+      receiver = receiver.accept<TreeNode>(v);
+      receiver?.parent = this;
+    }
+    if (index != null) {
+      index = index.accept<TreeNode>(v);
+      index?.parent = this;
+    }
+    if (value != null) {
+      value = value.accept<TreeNode>(v);
+      value?.parent = this;
+    }
+  }
+}
+
+/// Internal expression representing an if-null index assignment.
+///
+/// An if-null index assignment of the form `o[a] ??= b` is, if used for value,
+/// encoded as the expression:
+///
+///     let v1 = o in
+///     let v2 = a in
+///     let v3 = v1[v2] in
+///       v3 == null
+///        ? (let v4 = b in
+///           let _ = v1.[]=(v2, v4) in
+///           v4)
+///        : v3
+///
+/// and, if used for effect, encoded as the expression:
+///
+///     let v1 = o in
+///     let v2 = a in
+///     let v3 = v1[v2] in
+///        v3 == null ? v1.[]=(v2, b) : null
+///
+class IfNullIndexSet extends InternalExpression {
+  /// The receiver on which the index set operation is performed.
+  Expression receiver;
+
+  /// The index expression of the operation.
+  Expression index;
+
+  /// The value expression of the operation.
+  Expression value;
+
+  /// The file offset for the [] operation.
+  final int readOffset;
+
+  /// If `true`, the expression is only need for effect and not for its value.
+  final bool forEffect;
+
+  IfNullIndexSet(this.receiver, this.index, this.value, this.readOffset,
+      {this.forEffect})
+      : assert(forEffect != null) {
+    receiver?.parent = this;
+    index?.parent = this;
+    value?.parent = this;
+  }
+
+  @override
+  InternalExpressionKind get kind => InternalExpressionKind.IfNullIndexSet;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    receiver?.accept(v);
+    index?.accept(v);
+    value?.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (receiver != null) {
+      receiver = receiver.accept<TreeNode>(v);
+      receiver?.parent = this;
+    }
+    if (index != null) {
+      index = index.accept<TreeNode>(v);
+      index?.parent = this;
+    }
+    if (value != null) {
+      value = value.accept<TreeNode>(v);
+      value?.parent = this;
+    }
+  }
+}
+
+/// Internal expression representing an if-null index assignment.
+///
+/// An if-null index assignment of the form `o[a] += b` is, if used for value,
+/// encoded as the expression:
+///
+///     let v1 = o in
+///     let v2 = a in
+///     let v3 = v1.[](v2) + b
+///     let v4 = v1.[]=(v2, c3) in v3
+///
+/// and, if used for effect, encoded as the expression:
+///
+///     let v1 = o in let v2 = a in v1.[]=(v2, v1.[](v2) + b)
+///
+class CompoundIndexSet extends InternalExpression {
+  /// The receiver on which the index set operation is performed.
+  Expression receiver;
+
+  /// The index expression of the operation.
+  Expression index;
+
+  /// The name of the binary operation.
+  Name binaryName;
+
+  /// The right-hand side of the binary expression.
+  Expression rhs;
+
+  /// The file offset for the [] operation.
+  final int readOffset;
+
+  /// The file offset for the []= operation.
+  final int writeOffset;
+
+  /// The file offset for the binary operation.
+  final int binaryOffset;
+
+  /// If `true`, the expression is only need for effect and not for its value.
+  final bool forEffect;
+
+  /// If `true`, the expression is a post-fix inc/dec expression.
+  final bool forPostIncDec;
+
+  CompoundIndexSet(this.receiver, this.index, this.binaryName, this.rhs,
+      {this.readOffset,
+      this.binaryOffset,
+      this.writeOffset,
+      this.forEffect,
+      this.forPostIncDec})
+      : assert(forEffect != null) {
+    receiver?.parent = this;
+    index?.parent = this;
+    rhs?.parent = this;
+    fileOffset = binaryOffset;
+  }
+
+  @override
+  InternalExpressionKind get kind => InternalExpressionKind.CompoundIndexSet;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    receiver?.accept(v);
+    index?.accept(v);
+    rhs?.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (receiver != null) {
+      receiver = receiver.accept<TreeNode>(v);
+      receiver?.parent = this;
+    }
+    if (index != null) {
+      index = index.accept<TreeNode>(v);
+      index?.parent = this;
+    }
+    if (rhs != null) {
+      rhs = rhs.accept<TreeNode>(v);
+      rhs?.parent = this;
+    }
+  }
+}
+
+/// Creates a [Let] of [variable] with the given [body] using
+/// `variable.fileOffset` as the file offset for the let.
+///
+/// This is useful for create let expressions in replacement code.
+Let createLet(VariableDeclaration variable, Expression body) {
+  return new Let(variable, body)..fileOffset = variable.fileOffset;
+}
+
+/// Creates a [VariableDeclaration] for [expression] with the static [type]
+/// using `expression.fileOffset` as the file offset for the declaration.
+///
+/// This is useful for creating let variables for expressions in replacement
+/// code.
+VariableDeclaration createVariable(Expression expression, DartType type) {
+  return new VariableDeclaration.forValue(expression, type: type)
+    ..fileOffset = expression.fileOffset;
+}
+
+/// Creates a [VariableGet] of [variable] using `variable.fileOffset` as the
+/// file offset for the expression.
+///
+/// This is useful for referencing let variables for expressions in replacement
+/// code.
+VariableGet createVariableGet(VariableDeclaration variable) {
+  return new VariableGet(variable)..fileOffset = variable.fileOffset;
+}
+
+/// Creates a `e == null` test for the expression [left] using the [fileOffset]
+/// as file offset for the created nodes and [equalsMember] as the interface
+/// target of the created method invocation.
+MethodInvocation createEqualsNull(
+    int fileOffset, Expression left, Member equalsMember) {
+  return new MethodInvocation(
+      left,
+      new Name('=='),
+      new Arguments(<Expression>[new NullLiteral()..fileOffset = fileOffset])
+        ..fileOffset = fileOffset)
+    ..fileOffset = fileOffset
+    ..interfaceTarget = equalsMember;
+}
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 8755030..1c4a783 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -132,8 +132,6 @@
   final TypeBuilder bottomType =
       new NamedTypeBuilder("Null", const NullabilityBuilder.nullable(), null);
 
-  bool get legacyMode => backendTarget.legacyMode;
-
   final bool excludeSource = !CompilerContext.current.options.embedSourceText;
 
   final Map<String, String> environmentDefines =
@@ -268,7 +266,6 @@
           loader.checkSemantics(objectClassBuilder);
       loader.finishTypeVariables(objectClassBuilder, dynamicType);
       loader.buildComponent();
-      loader.finalizeInitializingFormals();
       installDefaultSupertypes();
       installSyntheticConstructors(myClasses);
       loader.resolveConstructors();
diff --git a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
index 4af23ec..ff2b557 100644
--- a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
@@ -7,7 +7,6 @@
 import 'package:kernel/ast.dart'
     show
         DartType,
-        DynamicType,
         Expression,
         ExpressionStatement,
         FunctionNode,
@@ -132,8 +131,7 @@
   RedirectionTarget(this.target, this.typeArguments);
 }
 
-RedirectionTarget getRedirectionTarget(Procedure member, EnsureLoaded helper,
-    {bool legacyMode}) {
+RedirectionTarget getRedirectionTarget(Procedure member, EnsureLoaded helper) {
   List<DartType> typeArguments = <DartType>[]..length =
       member.function.typeParameters.length;
   for (int i = 0; i < typeArguments.length; i++) {
@@ -155,27 +153,15 @@
     Member nextTortoise = tortoiseBody.target;
     helper.ensureLoaded(nextTortoise);
     List<DartType> nextTypeArguments = tortoiseBody.typeArguments;
-    if (!legacyMode && nextTypeArguments == null) {
+    if (nextTypeArguments == null) {
       nextTypeArguments = <DartType>[];
     }
 
-    if (!legacyMode || nextTypeArguments != null) {
-      Substitution sub = Substitution.fromPairs(
-          tortoise.function.typeParameters, typeArguments);
-      typeArguments = <DartType>[]..length = nextTypeArguments.length;
-      for (int i = 0; i < typeArguments.length; i++) {
-        typeArguments[i] = sub.substituteType(nextTypeArguments[i]);
-      }
-    } else {
-      // In Dart 1, we need to throw away the extra type arguments and use
-      // `dynamic` in place of the missing ones.
-      int typeArgumentCount = typeArguments.length;
-      int nextTypeArgumentCount =
-          nextTortoise.enclosingClass.typeParameters.length;
-      typeArguments.length = nextTypeArgumentCount;
-      for (int i = typeArgumentCount; i < nextTypeArgumentCount; i++) {
-        typeArguments[i] = const DynamicType();
-      }
+    Substitution sub =
+        Substitution.fromPairs(tortoise.function.typeParameters, typeArguments);
+    typeArguments = <DartType>[]..length = nextTypeArguments.length;
+    for (int i = 0; i < typeArguments.length; i++) {
+      typeArguments[i] = sub.substituteType(nextTypeArguments[i]);
     }
 
     tortoise = nextTortoise;
diff --git a/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
index e7d57d6..6e519f9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
@@ -429,7 +429,7 @@
     VariableDeclaration temp;
     if (entry.isNullAware) {
       temp = new VariableDeclaration.forValue(value,
-          type: coreTypes.mapClass.rawType);
+          type: coreTypes.mapLegacyRawType);
       body.add(temp);
       value = new VariableGet(temp);
     }
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 e176829..010f327 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
@@ -209,7 +209,8 @@
     }
 
     if (changed) {
-      return new FunctionTypeBuilder(returnType, variables, formals);
+      return new FunctionTypeBuilder(
+          returnType, variables, formals, type.nullabilityBuilder);
     }
 
     return type;
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 5f6dfb0..1c060a6 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
@@ -114,8 +114,8 @@
           new FormalParameterBuilder(null, 0, type, parameter.name, null, -1)
             ..kind = FormalParameterKind.optionalNamed;
     }
-
-    return new FunctionTypeBuilder(returnType, typeVariables, formals);
+    return new FunctionTypeBuilder(returnType, typeVariables, formals,
+        new NullabilityBuilder.fromNullability(node.nullability));
   }
 
   TypeBuilder visitTypeParameterType(TypeParameterType node) {
@@ -123,10 +123,8 @@
     Class kernelClass = parameter.parent;
     Library kernelLibrary = kernelClass.enclosingLibrary;
     LibraryBuilder library = loader.builders[kernelLibrary.importUri];
-    // TODO(dmitryas): Compute the nullabilityBuilder field for the result from
-    //  the nullability field of 'node'.
-    return new NamedTypeBuilder(
-        parameter.name, const NullabilityBuilder.pendingImplementation(), null)
+    return new NamedTypeBuilder(parameter.name,
+        new NullabilityBuilder.fromNullability(node.nullability), null)
       ..bind(new TypeVariableBuilder.fromKernel(parameter, library));
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/verifier.dart b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
index ac24a09..4f0387f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/verifier.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
@@ -12,6 +12,7 @@
         DartType,
         ExpressionStatement,
         Field,
+        FunctionType,
         Let,
         Library,
         Member,
@@ -20,7 +21,8 @@
         SuperMethodInvocation,
         SuperPropertyGet,
         SuperPropertySet,
-        TreeNode;
+        TreeNode,
+        TypeParameter;
 
 import 'package:kernel/transformations/flags.dart' show TransformerFlag;
 
@@ -183,6 +185,20 @@
   }
 
   @override
+  visitFunctionType(FunctionType node) {
+    if (node.typeParameters.isNotEmpty) {
+      for (TypeParameter typeParameter in node.typeParameters) {
+        if (typeParameter.parent != null) {
+          problem(
+              null,
+              "Type parameters of function types shouldn't have parents: "
+              "$node.");
+        }
+      }
+    }
+  }
+
+  @override
   visitSuperMethodInvocation(SuperMethodInvocation node) {
     checkSuperInvocation(node);
     super.visitSuperMethodInvocation(node);
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 9ad4e92..c185f92 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -3428,6 +3428,10 @@
       //
       // 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
@@ -4178,12 +4182,17 @@
     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
diff --git a/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart
index e34362d..cae857c 100644
--- a/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart
@@ -73,6 +73,10 @@
   /// and https://github.com/dart-lang/language/issues/60
   bool _enableTripleShift = false;
 
+  /// Experimental flag for enabling variance.
+  /// See https://github.com/dart-lang/language/issues/524
+  bool _enableVariance = false;
+
   /**
    * The string offset for the next token that will be created.
    *
@@ -139,6 +143,7 @@
       _enableExtensionMethods = config.enableExtensionMethods;
       _enableNonNullable = config.enableNonNullable;
       _enableTripleShift = config.enableTripleShift;
+      _enableVariance = config.enableVariance;
     }
   }
 
@@ -1483,6 +1488,10 @@
         (state.keyword == Keyword.LATE || state.keyword == Keyword.REQUIRED)) {
       return tokenizeIdentifier(next, start, allowDollar);
     }
+    if (!_enableVariance &&
+        (state.keyword == Keyword.OUT || state.keyword == Keyword.INOUT)) {
+      return tokenizeIdentifier(next, start, allowDollar);
+    }
     if (($A <= next && next <= $Z) ||
         ($0 <= next && next <= $9) ||
         identical(next, $_) ||
@@ -1907,13 +1916,19 @@
   /// and https://github.com/dart-lang/language/issues/60
   final bool enableTripleShift;
 
+  /// Experimental flag for enabling variance.
+  /// See https://github.com/dart-lang/language/issues/524
+  final bool enableVariance;
+
   const ScannerConfiguration({
     bool enableExtensionMethods,
     bool enableNonNullable,
     bool enableTripleShift,
+    bool enableVariance,
   })  : this.enableExtensionMethods = enableExtensionMethods ?? false,
         this.enableNonNullable = enableNonNullable ?? false,
-        this.enableTripleShift = enableTripleShift ?? false;
+        this.enableTripleShift = enableTripleShift ?? false,
+        this.enableVariance = enableVariance ?? false;
 }
 
 bool _isIdentifierChar(int next, bool allowDollar) {
diff --git a/pkg/front_end/lib/src/fasta/severity.dart b/pkg/front_end/lib/src/fasta/severity.dart
index d3eb763..71f1cd6 100644
--- a/pkg/front_end/lib/src/fasta/severity.dart
+++ b/pkg/front_end/lib/src/fasta/severity.dart
@@ -7,6 +7,7 @@
 enum Severity {
   context,
   error,
+  // TODO(johnniwinther): Remove legacy warning.
   errorLegacyWarning,
   ignored,
   internalProblem,
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 13ee5bc..d2272da 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -19,7 +19,6 @@
         Message,
         messageConstConstructorWithBody,
         messageConstInstanceField,
-        messageConstMethod,
         messageConstructorWithReturnType,
         messageConstructorWithTypeParameters,
         messageExpectedBlockToSkip,
@@ -1031,7 +1030,8 @@
           beginInitializers: beginInitializers);
     } else {
       if (isConst) {
-        addProblem(messageConstMethod, varFinalOrConstOffset, 5);
+        // TODO(danrubel): consider removing this
+        // because it is an error to have a const method.
         modifiers &= ~constMask;
       }
       final int startCharOffset =
@@ -1388,7 +1388,11 @@
     TypeBuilder returnType = pop();
     List<TypeVariableBuilder> typeVariables = pop();
     push(library.addFunctionType(
-        returnType, typeVariables, formals, functionToken.charOffset));
+        returnType,
+        typeVariables,
+        formals,
+        library.computeNullabilityFromToken(questionMark != null),
+        functionToken.charOffset));
   }
 
   @override
@@ -1401,8 +1405,8 @@
     if (!library.loader.target.enableNonNullable) {
       reportErrorIfNullableType(question);
     }
-    push(library.addFunctionType(
-        returnType, typeVariables, formals, formalsOffset));
+    push(library.addFunctionType(returnType, typeVariables, formals,
+        library.computeNullabilityFromToken(question != null), formalsOffset));
   }
 
   @override
@@ -1432,8 +1436,9 @@
       library.beginNestedDeclaration(
           TypeParameterScopeKind.functionType, "#function_type",
           hasMembers: false);
-      functionType =
-          library.addFunctionType(returnType, null, formals, charOffset);
+      // TODO(dmitryas): Make sure that RHS of typedefs can't have '?'.
+      functionType = library.addFunctionType(returnType, null, formals,
+          const NullabilityBuilder.omitted(), charOffset);
     } else {
       Object type = pop();
       typeVariables = pop();
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 308acca..3ef57cb 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
@@ -255,8 +255,6 @@
 
   final List<Object> accessors = <Object>[];
 
-  final bool legacyMode;
-
   String documentationComment;
 
   String name;
@@ -317,8 +315,6 @@
   /// the error message is the corresponding value in the map.
   Map<String, String> unserializableExports;
 
-  List<FormalParameterBuilder> untypedInitializingFormals;
-
   List<FieldBuilder> implicitlyTypedFields;
 
   bool languageVersionExplicitlySet = false;
@@ -346,7 +342,6 @@
       this.library,
       this._nameOrigin)
       : currentTypeParameterScopeBuilder = libraryDeclaration,
-        legacyMode = loader.target.legacyMode,
         super(
             fileUri, libraryDeclaration.toScope(importScope), new Scope.top());
 
@@ -623,8 +618,7 @@
       bool isFinal = modifiers & finalMask != 0;
       bool potentiallyNeedInitializerInOutline = isConst || isFinal;
       Token startToken;
-      if (potentiallyNeedInitializerInOutline ||
-          (type == null && !legacyMode)) {
+      if (potentiallyNeedInitializerInOutline || type == null) {
         startToken = info.initializerToken;
       }
       if (startToken != null) {
@@ -1096,11 +1090,7 @@
     int typeCount = types.length;
     for (UnresolvedType t in types) {
       t.resolveIn(scope, this);
-      if (!loader.target.legacyMode) {
-        t.checkType(this);
-      } else {
-        t.normalizeType();
-      }
+      t.checkType(this);
     }
     types.clear();
     return typeCount;
@@ -1767,7 +1757,7 @@
         metadata, type, name, modifiers, this, charOffset, charEndOffset);
     fieldBuilder.constInitializerToken = constInitializerToken;
     addBuilder(name, fieldBuilder, charOffset);
-    if (!legacyMode && type == null && initializerToken != null) {
+    if (type == null && initializerToken != null) {
       fieldBuilder.field.type =
           new ImplicitFieldType(fieldBuilder, initializerToken);
       (implicitlyTypedFields ??= <FieldBuilder>[]).add(fieldBuilder);
@@ -2001,9 +1991,10 @@
       TypeBuilder returnType,
       List<TypeVariableBuilder> typeVariables,
       List<FormalParameterBuilder> formals,
+      NullabilityBuilder nullabilityBuilder,
       int charOffset) {
-    FunctionTypeBuilder builder =
-        new FunctionTypeBuilder(returnType, typeVariables, formals);
+    FunctionTypeBuilder builder = new FunctionTypeBuilder(
+        returnType, typeVariables, formals, nullabilityBuilder);
     checkTypeVariables(typeVariables, null);
     // Nested declaration began in `OutlineBuilder.beginFunctionType` or
     // `OutlineBuilder.beginFunctionTypedFormalParameter`.
@@ -2026,9 +2017,6 @@
     FormalParameterBuilder formal = new FormalParameterBuilder(
         metadata, modifiers, type, name, this, charOffset);
     formal.initializerToken = initializerToken;
-    if (legacyMode && hasThis && type == null) {
-      (untypedInitializingFormals ??= <FormalParameterBuilder>[]).add(formal);
-    }
     return formal;
   }
 
@@ -2383,12 +2371,12 @@
       ClassBuilder objectClass) {
     int count = 0;
 
-    int computeDefaultTypesForVariables(
-        List<TypeVariableBuilder> variables, bool legacyMode) {
+    int computeDefaultTypesForVariables(List<TypeVariableBuilder> variables,
+        {bool inErrorRecovery}) {
       if (variables == null) return 0;
 
       bool haveErroneousBounds = false;
-      if (!legacyMode) {
+      if (!inErrorRecovery) {
         for (int i = 0; i < variables.length; ++i) {
           TypeVariableBuilder variable = variables[i];
           List<TypeBuilder> genericFunctionTypes = <TypeBuilder>[];
@@ -2410,8 +2398,8 @@
         }
       }
 
-      if (legacyMode || haveErroneousBounds) {
-        // In Dart 1, put `dynamic` everywhere.
+      if (inErrorRecovery || haveErroneousBounds) {
+        // Use dynamic in case of errors.
         for (int i = 0; i < variables.length; ++i) {
           variables[i].defaultType = dynamicType;
         }
@@ -2432,47 +2420,37 @@
       }
     }
 
-    bool legacyMode = loader.target.legacyMode;
     for (Builder declaration in libraryDeclaration.members.values) {
       if (declaration is ClassBuilder) {
         {
-          List<Object> issues = legacyMode
-              ? const <Object>[]
-              : getNonSimplicityIssuesForDeclaration(declaration,
-                  performErrorRecovery: true);
+          List<Object> issues = getNonSimplicityIssuesForDeclaration(
+              declaration,
+              performErrorRecovery: true);
           reportIssues(issues);
-          // In case of issues, use legacy mode for error recovery.
-          count += computeDefaultTypesForVariables(
-              declaration.typeVariables, legacyMode || issues.isNotEmpty);
+          count += computeDefaultTypesForVariables(declaration.typeVariables,
+              inErrorRecovery: issues.isNotEmpty);
         }
         declaration.forEach((String name, Builder member) {
           if (member is ProcedureBuilder) {
-            List<Object> issues = legacyMode
-                ? const <Object>[]
-                : getNonSimplicityIssuesForTypeVariables(member.typeVariables);
+            List<Object> issues =
+                getNonSimplicityIssuesForTypeVariables(member.typeVariables);
             reportIssues(issues);
-            // In case of issues, use legacy mode for error recovery.
-            count += computeDefaultTypesForVariables(
-                member.typeVariables, legacyMode || issues.isNotEmpty);
+            count += computeDefaultTypesForVariables(member.typeVariables,
+                inErrorRecovery: issues.isNotEmpty);
           }
         });
       } else if (declaration is TypeAliasBuilder) {
-        List<Object> issues = legacyMode
-            ? const <Object>[]
-            : getNonSimplicityIssuesForDeclaration(declaration,
-                performErrorRecovery: true);
+        List<Object> issues = getNonSimplicityIssuesForDeclaration(declaration,
+            performErrorRecovery: true);
         reportIssues(issues);
-        // In case of issues, use legacy mode for error recovery.
-        count += computeDefaultTypesForVariables(
-            declaration.typeVariables, legacyMode || issues.isNotEmpty);
+        count += computeDefaultTypesForVariables(declaration.typeVariables,
+            inErrorRecovery: issues.isNotEmpty);
       } else if (declaration is FunctionBuilder) {
-        List<Object> issues = legacyMode
-            ? const <Object>[]
-            : getNonSimplicityIssuesForTypeVariables(declaration.typeVariables);
+        List<Object> issues =
+            getNonSimplicityIssuesForTypeVariables(declaration.typeVariables);
         reportIssues(issues);
-        // In case of issues, use legacy mode for error recovery.
-        count += computeDefaultTypesForVariables(
-            declaration.typeVariables, legacyMode || issues.isNotEmpty);
+        count += computeDefaultTypesForVariables(declaration.typeVariables,
+            inErrorRecovery: issues.isNotEmpty);
       }
     }
 
@@ -2637,7 +2615,6 @@
   }
 
   void checkBoundsInField(Field field, TypeEnvironment typeEnvironment) {
-    if (loader.target.legacyMode) return;
     checkBoundsInType(
         field.type, typeEnvironment, field.fileUri, field.fileOffset,
         allowSuperBounded: true);
@@ -2649,7 +2626,6 @@
       List<VariableDeclaration> positionalParameters,
       List<VariableDeclaration> namedParameters,
       DartType returnType}) {
-    if (loader.target.legacyMode) return;
     if (typeParameters != null) {
       for (TypeParameter parameter in typeParameters) {
         checkBoundsInType(
@@ -2704,7 +2680,6 @@
 
   void checkBoundsInFunctionNode(
       FunctionNode function, TypeEnvironment typeEnvironment, Uri fileUri) {
-    if (loader.target.legacyMode) return;
     checkBoundsInFunctionNodeParts(
         typeEnvironment, fileUri, function.fileOffset,
         typeParameters: function.typeParameters,
@@ -2716,7 +2691,6 @@
   void checkBoundsInListLiteral(
       ListLiteral node, TypeEnvironment typeEnvironment, Uri fileUri,
       {bool inferred = false}) {
-    if (loader.target.legacyMode) return;
     checkBoundsInType(
         node.typeArgument, typeEnvironment, fileUri, node.fileOffset,
         inferred: inferred, allowSuperBounded: true);
@@ -2725,7 +2699,6 @@
   void checkBoundsInSetLiteral(
       SetLiteral node, TypeEnvironment typeEnvironment, Uri fileUri,
       {bool inferred = false}) {
-    if (loader.target.legacyMode) return;
     checkBoundsInType(
         node.typeArgument, typeEnvironment, fileUri, node.fileOffset,
         inferred: inferred, allowSuperBounded: true);
@@ -2734,7 +2707,6 @@
   void checkBoundsInMapLiteral(
       MapLiteral node, TypeEnvironment typeEnvironment, Uri fileUri,
       {bool inferred = false}) {
-    if (loader.target.legacyMode) return;
     checkBoundsInType(node.keyType, typeEnvironment, fileUri, node.fileOffset,
         inferred: inferred, allowSuperBounded: true);
     checkBoundsInType(node.valueType, typeEnvironment, fileUri, node.fileOffset,
@@ -2744,7 +2716,6 @@
   void checkBoundsInType(
       DartType type, TypeEnvironment typeEnvironment, Uri fileUri, int offset,
       {bool inferred, bool allowSuperBounded = true}) {
-    if (loader.target.legacyMode) return;
     List<TypeArgumentIssue> issues = findTypeArgumentIssues(
         type, typeEnvironment,
         allowSuperBounded: allowSuperBounded);
@@ -2756,7 +2727,6 @@
   void checkBoundsInVariableDeclaration(
       VariableDeclaration node, TypeEnvironment typeEnvironment, Uri fileUri,
       {bool inferred = false}) {
-    if (loader.target.legacyMode) return;
     if (node.type == null) return;
     checkBoundsInType(node.type, typeEnvironment, fileUri, node.fileOffset,
         inferred: inferred, allowSuperBounded: true);
@@ -2765,7 +2735,6 @@
   void checkBoundsInConstructorInvocation(
       ConstructorInvocation node, TypeEnvironment typeEnvironment, Uri fileUri,
       {bool inferred = false}) {
-    if (loader.target.legacyMode) return;
     if (node.arguments.types.isEmpty) return;
     Constructor constructor = node.target;
     Class klass = constructor.enclosingClass;
@@ -2778,7 +2747,6 @@
   void checkBoundsInFactoryInvocation(
       StaticInvocation node, TypeEnvironment typeEnvironment, Uri fileUri,
       {bool inferred = false}) {
-    if (loader.target.legacyMode) return;
     if (node.arguments.types.isEmpty) return;
     Procedure factory = node.target;
     assert(factory.isFactory);
@@ -2792,7 +2760,6 @@
   void checkBoundsInStaticInvocation(
       StaticInvocation node, TypeEnvironment typeEnvironment, Uri fileUri,
       {bool inferred = false}) {
-    if (loader.target.legacyMode) return;
     if (node.arguments.types.isEmpty) return;
     Class klass = node.target.enclosingClass;
     List<TypeParameter> parameters = node.target.function.typeParameters;
@@ -2825,7 +2792,6 @@
       Uri fileUri,
       int offset,
       {bool inferred = false}) {
-    if (loader.target.legacyMode) return;
     if (arguments.types.isEmpty) return;
     Class klass;
     List<DartType> receiverTypeArguments;
@@ -2876,7 +2842,6 @@
   }
 
   void checkBoundsInOutline(TypeEnvironment typeEnvironment) {
-    if (loader.target.legacyMode) return;
     Iterator<Builder> iterator = this.iterator;
     while (iterator.moveNext()) {
       Builder declaration = iterator.current;
@@ -2892,16 +2857,6 @@
     inferredTypes.clear();
   }
 
-  int finalizeInitializingFormals() {
-    if (!legacyMode || untypedInitializingFormals == null) return 0;
-    for (int i = 0; i < untypedInitializingFormals.length; i++) {
-      untypedInitializingFormals[i].finalizeInitializingFormal();
-    }
-    int count = untypedInitializingFormals.length;
-    untypedInitializingFormals = null;
-    return count;
-  }
-
   @override
   List<FieldBuilder> takeImplicitlyTypedFields() {
     List<FieldBuilder> result = implicitlyTypedFields;
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 f9a2a91..eeb0bac 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -474,17 +474,6 @@
     ticker.logMs("Resolved $typeCount types");
   }
 
-  void finalizeInitializingFormals() {
-    int formalCount = 0;
-    builders.forEach((Uri uri, LibraryBuilder library) {
-      if (library.loader == this) {
-        SourceLibraryBuilder sourceLibrary = library;
-        formalCount += sourceLibrary.finalizeInitializingFormals();
-      }
-    });
-    ticker.logMs("Finalized $formalCount initializing formals");
-  }
-
   void finishDeferredLoadTearoffs() {
     int count = 0;
     builders.forEach((Uri uri, LibraryBuilder library) {
@@ -890,8 +879,6 @@
   }
 
   void checkBounds() {
-    if (target.legacyMode) return;
-
     builders.forEach((Uri uri, LibraryBuilder library) {
       if (library is SourceLibraryBuilder) {
         if (library.loader == this) {
@@ -935,7 +922,6 @@
 
   void checkRedirectingFactories(List<SourceClassBuilder> sourceClasses) {
     // TODO(ahe): Move this to [ClassHierarchyBuilder].
-    if (target.legacyMode) return;
     for (SourceClassBuilder builder in sourceClasses) {
       if (builder.library.loader == this && !builder.isPatch) {
         builder.checkRedirectingFactories(
@@ -999,13 +985,10 @@
   }
 
   void createTypeInferenceEngine() {
-    if (target.legacyMode) return;
     typeInferenceEngine = new ShadowTypeInferenceEngine(instrumentation);
   }
 
   void performTopLevelInference(List<SourceClassBuilder> sourceClasses) {
-    if (target.legacyMode) return;
-
     /// The first phase of top level initializer inference, which consists of
     /// creating kernel objects for all fields and top level variables that
     /// might be subject to type inference, and records dependencies between
diff --git a/pkg/front_end/lib/src/fasta/target_implementation.dart b/pkg/front_end/lib/src/fasta/target_implementation.dart
index e6ada23..4aa0538 100644
--- a/pkg/front_end/lib/src/fasta/target_implementation.dart
+++ b/pkg/front_end/lib/src/fasta/target_implementation.dart
@@ -154,7 +154,7 @@
   Severity fixSeverity(Severity severity, Message message, Uri fileUri) {
     severity ??= message.code.severity;
     if (severity == Severity.errorLegacyWarning) {
-      severity = backendTarget.legacyMode ? Severity.warning : Severity.error;
+      severity = Severity.error;
     }
     return rewriteSeverity(severity, message.code, fileUri);
   }
diff --git a/pkg/front_end/lib/src/fasta/type_inference/inference_helper.dart b/pkg/front_end/lib/src/fasta/type_inference/inference_helper.dart
index d08f492..f01923c 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/inference_helper.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/inference_helper.dart
@@ -22,7 +22,9 @@
   set transformSetLiterals(bool value);
 
   Expression buildProblem(Message message, int charOffset, int length,
-      {List<LocatedMessage> context, bool suppressMessage});
+      {List<LocatedMessage> context,
+      bool suppressMessage,
+      bool wrapInSyntheticExpression: true});
 
   LocatedMessage checkArgumentsForType(
       FunctionType function, Arguments arguments, int offset);
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 982987c..0fb91de 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
@@ -14,6 +14,7 @@
         InterfaceType,
         InvalidType,
         NamedType,
+        Nullability,
         TypeParameterType,
         VoidType;
 
@@ -337,7 +338,8 @@
     // TODO(paulberry): We could do better here, e.g.:
     //   SUB(([int]) -> void, (int) -> void) = (int) -> void
     if (f.requiredParameterCount != g.requiredParameterCount) {
-      return functionClass.rawType;
+      return new InterfaceType(
+          functionClass, const <DynamicType>[], Nullability.legacy);
     }
     int requiredParameterCount = f.requiredParameterCount;
 
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 3912f27..930810e 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
@@ -298,17 +298,10 @@
       DartType supertypeArg = supertype.typeArguments[0];
       DartType supertypeFuture = futureType(supertypeArg);
 
-      // The outcome of both trySubtypeMatch and _isSubtypeMatch is includes the
-      // returned boolean value and the added constraints to _protoConstraints.
-      // Here we need to match 'subtype' against both possibilities of the
-      // FutureOr<X> which is 'supertype,' that is, we need to match 'subtype'
-      // against Future<X> and X.  However, if the first matching against
-      // Future<X> finds any new constraints and adds them to _protoConstraints,
-      // we should prefer them over the constraints possibly found while
-      // matching against X.  Note that if matching against Future<X> returned
-      // true, but didn't find any new constraints, then matching against X
-      // should still be done and the new constraints should still be added to
-      // _protoConstraints.
+      // The match against FutureOr<X> succeeds if the match against either
+      // Future<X> or X succeeds.  If they both succeed, the one adding new
+      // constraints should be preferred.  If both matches against Future<X> and
+      // X add new constraints, the former should be preferred over the latter.
       int oldProtoConstraintsLength = _protoConstraints.length;
       bool matchesFuture = trySubtypeMatch(subtype, supertypeFuture);
       bool matchesArg = oldProtoConstraintsLength != _protoConstraints.length
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 f01431a..9bb90d0 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -2,58 +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.md file.
 
-import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart';
-import 'package:kernel/ast.dart' as kernel;
+import 'dart:core' hide MapEntry;
 
-import 'package:kernel/ast.dart'
-    show
-        Arguments,
-        AsExpression,
-        AsyncMarker,
-        BottomType,
-        Class,
-        ConditionalExpression,
-        ConstructorInvocation,
-        DartType,
-        DynamicType,
-        Expression,
-        Extension,
-        Field,
-        FunctionExpression,
-        FunctionNode,
-        FunctionType,
-        Instantiation,
-        InterfaceType,
-        InvalidType,
-        InvocationExpression,
-        Let,
-        ListLiteral,
-        MapLiteral,
-        Member,
-        MethodInvocation,
-        Name,
-        NullLiteral,
-        Procedure,
-        ProcedureKind,
-        PropertyGet,
-        PropertySet,
-        ReturnStatement,
-        SetLiteral,
-        Statement,
-        StaticGet,
-        StaticInvocation,
-        SuperMethodInvocation,
-        SuperPropertyGet,
-        SuperPropertySet,
-        Supertype,
-        ThisExpression,
-        TreeNode,
-        TypeParameter,
-        TypeParameterType,
-        VariableDeclaration,
-        VariableGet,
-        VoidType,
-        setParents;
+import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart';
+
+import 'package:kernel/ast.dart';
 
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 
@@ -86,8 +39,6 @@
         templateArgumentTypeNotAssignable,
         templateDuplicatedNamedArgument,
         templateImplicitCallOfNonMethod,
-        templateInternalProblemNoInferredTypeStored,
-        templateInternalProblemStoringMultipleInferredTypes,
         templateInvalidAssignment,
         templateInvalidCastFunctionExpr,
         templateInvalidCastLiteralList,
@@ -107,10 +58,9 @@
 
 import '../kernel/kernel_shadow_ast.dart'
     show
-        ExpressionJudgment,
         ShadowTypeInferenceEngine,
         ShadowTypeInferrer,
-        VariableDeclarationJudgment,
+        VariableDeclarationImpl,
         getExplicitTypeArguments,
         getExtensionTypeParameterCount;
 
@@ -118,7 +68,7 @@
 
 import '../names.dart' show callName, unaryMinusName;
 
-import '../problems.dart' show internalProblem, unexpected, unhandled;
+import '../problems.dart' show unexpected, unhandled;
 
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 
@@ -262,7 +212,7 @@
       // Null.
       if (flattenedReturnType is VoidType ||
           flattenedReturnType is DynamicType ||
-          flattenedReturnType == inferrer.coreTypes.nullClass.rawType) {
+          flattenedReturnType == inferrer.coreTypes.nullType) {
         return true;
       }
       statement.expression = inferrer.helper.wrapInProblem(
@@ -287,7 +237,7 @@
     if (returnType is VoidType &&
         flattenedExpressionType is! VoidType &&
         flattenedExpressionType is! DynamicType &&
-        flattenedExpressionType != inferrer.coreTypes.nullClass.rawType) {
+        flattenedExpressionType != inferrer.coreTypes.nullType) {
       statement.expression = inferrer.helper.wrapInProblem(
           statement.expression, messageReturnFromVoidFunction, noLength)
         ..parent = statement;
@@ -300,7 +250,7 @@
     if (flattenedExpressionType is VoidType &&
         flattenedReturnType is! VoidType &&
         flattenedReturnType is! DynamicType &&
-        flattenedReturnType != inferrer.coreTypes.nullClass.rawType) {
+        flattenedReturnType != inferrer.coreTypes.nullType) {
       statement.expression = inferrer.helper
           .wrapInProblem(statement.expression, messageVoidExpression, noLength)
             ..parent = statement;
@@ -475,28 +425,27 @@
   Uri get uri;
 
   /// Performs full type inference on the given field initializer.
-  void inferFieldInitializer(InferenceHelper helper, DartType declaredType,
-      kernel.Expression initializer);
+  void inferFieldInitializer(
+      InferenceHelper helper, DartType declaredType, Expression initializer);
 
   /// Performs type inference on the given function body.
   void inferFunctionBody(InferenceHelper helper, DartType returnType,
       AsyncMarker asyncMarker, Statement body);
 
   /// Performs type inference on the given constructor initializer.
-  void inferInitializer(InferenceHelper helper, kernel.Initializer initializer);
+  void inferInitializer(InferenceHelper helper, Initializer initializer);
 
   /// Performs type inference on the given metadata annotations.
-  void inferMetadata(
-      InferenceHelper helper, List<kernel.Expression> annotations);
+  void inferMetadata(InferenceHelper helper, List<Expression> annotations);
 
   /// Performs type inference on the given metadata annotations keeping the
   /// existing helper if possible.
-  void inferMetadataKeepingHelper(List<kernel.Expression> annotations);
+  void inferMetadataKeepingHelper(List<Expression> annotations);
 
   /// Performs type inference on the given function parameter initializer
   /// expression.
-  void inferParameterInitializer(InferenceHelper helper,
-      kernel.Expression initializer, DartType declaredType);
+  void inferParameterInitializer(
+      InferenceHelper helper, Expression initializer, DartType declaredType);
 }
 
 /// Derived class containing generic implementations of [TypeInferrer].
@@ -531,8 +480,6 @@
   @override
   final SourceLibraryBuilder library;
 
-  final Map<TreeNode, DartType> inferredTypesMap = <TreeNode, DartType>{};
-
   InferenceHelper helper;
 
   /// Context information for the current closure, or `null` if we are not
@@ -556,32 +503,6 @@
         isTopLevel = topLevel,
         super.private(engine.coreTypes);
 
-  DartType storeInferredType(TreeNode node, DartType type) {
-    if (node is ExpressionJudgment) {
-      return node.inferredType = type;
-    } else {
-      if (inferredTypesMap.containsKey(node)) {
-        internalProblem(
-            templateInternalProblemStoringMultipleInferredTypes.withArguments(
-                inferredTypesMap[node], "${node.runtimeType}"),
-            node.fileOffset,
-            uri);
-      }
-      return inferredTypesMap[node] = type;
-    }
-  }
-
-  DartType readInferredType(TreeNode node) {
-    if (!inferredTypesMap.containsKey(node) && !isTopLevel) {
-      internalProblem(
-          templateInternalProblemNoInferredTypeStored
-              .withArguments("${node.runtimeType}"),
-          node.fileOffset,
-          uri);
-    }
-    return inferredTypesMap[node];
-  }
-
   /// Gets the type promoter that should be used to promote types during
   /// inference.
   TypePromoter get typePromoter;
@@ -599,7 +520,8 @@
       InterfaceType type = typeContext;
       typeContext = type.typeArguments.first;
     }
-    return typeContext == coreTypes.doubleClass.rawType;
+    return typeContext is InterfaceType &&
+        typeContext.classNode == coreTypes.doubleClass;
   }
 
   bool isAssignable(DartType expectedType, DartType actualType) {
@@ -758,10 +680,7 @@
   /// be targeted due to, e.g., an incorrect argument count).
   ObjectAccessTarget findInterfaceMember(
       DartType receiverType, Name name, int fileOffset,
-      {Template<Message Function(String, DartType)> errorTemplate,
-      Expression expression,
-      Expression receiver,
-      bool setter: false,
+      {bool setter: false,
       bool instrumented: true,
       bool includeExtensionMethods: false}) {
     assert(receiverType != null && isKnown(receiverType));
@@ -777,9 +696,19 @@
         : coreTypes.objectClass;
     Member interfaceMember =
         _getInterfaceMember(classNode, name, setter, fileOffset);
-    ObjectAccessTarget target = interfaceMember != null
-        ? new ObjectAccessTarget.interfaceMember(interfaceMember)
-        : const ObjectAccessTarget.unresolved();
+    ObjectAccessTarget target;
+    if (interfaceMember != null) {
+      target = new ObjectAccessTarget.interfaceMember(interfaceMember);
+    } else if (receiverType is DynamicType) {
+      target = const ObjectAccessTarget.dynamic();
+    } else if (receiverType is InvalidType) {
+      target = const ObjectAccessTarget.invalid();
+    } else if (receiverType == coreTypes.functionLegacyRawType &&
+        name.name == 'call') {
+      target = const ObjectAccessTarget.callFunction();
+    } else {
+      target = const ObjectAccessTarget.missing();
+    }
     if (instrumented &&
         receiverType != const DynamicType() &&
         target.isInstanceMember) {
@@ -881,14 +810,41 @@
         // one potential targets were found.
       }
     }
+    return target;
+  }
 
-    if (!isTopLevel &&
-        target.isUnresolved &&
-        receiverType is! DynamicType &&
-        receiverType is! InvalidType &&
-        !(receiverType == coreTypes.functionClass.rawType &&
-            name.name == 'call') &&
-        errorTemplate != null) {
+  /// 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(
+      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);
+
+    assert(receiverType != null && isKnown(receiverType));
+    if (!isTopLevel && target.isMissing && errorTemplate != null) {
       int length = name.name.length;
       if (identical(name.name, callName.name) ||
           identical(name.name, unaryMinusName.name)) {
@@ -897,7 +853,8 @@
       expression.parent.replaceChild(
           expression,
           helper.desugarSyntheticExpression(helper.buildProblem(
-              errorTemplate.withArguments(name.name, receiverType),
+              errorTemplate.withArguments(
+                  name.name, resolveTypeParameter(receiverType)),
               fileOffset,
               length)));
     }
@@ -912,11 +869,12 @@
     // TODO(paulberry): could we add getters to InvocationExpression to make
     // these is-checks unnecessary?
     if (methodInvocation is MethodInvocation) {
-      ObjectAccessTarget interfaceTarget = findInterfaceMember(
-          receiverType, methodInvocation.name, methodInvocation.fileOffset,
-          errorTemplate: templateUndefinedMethod,
-          expression: methodInvocation,
-          receiver: methodInvocation.receiver,
+      ObjectAccessTarget interfaceTarget = findInterfaceMemberOrReport(
+          receiverType,
+          methodInvocation.name,
+          methodInvocation.fileOffset,
+          templateUndefinedMethod,
+          methodInvocation,
           instrumented: instrumented,
           includeExtensionMethods: true);
       if (interfaceTarget.isInstanceMember) {
@@ -930,7 +888,7 @@
                   signature.positionalParameters.length) {
             return const ObjectAccessTarget.unresolved();
           }
-          for (kernel.NamedExpression argument in arguments.named) {
+          for (NamedExpression argument in arguments.named) {
             if (!signature.namedParameters
                 .any((declaration) => declaration.name == argument.name)) {
               return const ObjectAccessTarget.unresolved();
@@ -967,11 +925,12 @@
     // 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 = findInterfaceMember(
-          receiverType, propertyGet.name, propertyGet.fileOffset,
-          errorTemplate: templateUndefinedGetter,
-          expression: propertyGet,
-          receiver: propertyGet.receiver,
+      ObjectAccessTarget readTarget = findInterfaceMemberOrReport(
+          receiverType,
+          propertyGet.name,
+          propertyGet.fileOffset,
+          templateUndefinedGetter,
+          propertyGet,
           instrumented: instrumented);
       if (readTarget.isInstanceMember) {
         if (instrumented &&
@@ -1004,11 +963,12 @@
       DartType receiverType, Expression propertySet,
       {bool instrumented: true}) {
     if (propertySet is PropertySet) {
-      ObjectAccessTarget writeTarget = findInterfaceMember(
-          receiverType, propertySet.name, propertySet.fileOffset,
-          errorTemplate: templateUndefinedSetter,
-          expression: propertySet,
-          receiver: propertySet.receiver,
+      ObjectAccessTarget writeTarget = findInterfaceMemberOrReport(
+          receiverType,
+          propertySet.name,
+          propertySet.fileOffset,
+          templateUndefinedSetter,
+          propertySet,
           setter: true,
           instrumented: instrumented,
           includeExtensionMethods: true);
@@ -1055,6 +1015,9 @@
       case ObjectAccessTargetKind.callFunction:
         return receiverType;
       case ObjectAccessTargetKind.unresolved:
+      case ObjectAccessTargetKind.dynamic:
+      case ObjectAccessTargetKind.invalid:
+      case ObjectAccessTargetKind.missing:
         return const DynamicType();
       case ObjectAccessTargetKind.instanceMember:
         return getGetterTypeForMemberTarget(target.member, receiverType);
@@ -1111,8 +1074,7 @@
   DartType getGetterTypeForMemberTarget(
       Member interfaceMember, DartType receiverType) {
     Class memberClass = interfaceMember.enclosingClass;
-    assert(
-        interfaceMember is kernel.Field || interfaceMember is kernel.Procedure,
+    assert(interfaceMember is Field || interfaceMember is Procedure,
         "Unexpected interface member $interfaceMember.");
     DartType calleeType = interfaceMember.getterType;
     if (memberClass.typeParameters.isNotEmpty) {
@@ -1151,6 +1113,9 @@
       case ObjectAccessTargetKind.callFunction:
         return _getFunctionType(receiverType, followCall);
       case ObjectAccessTargetKind.unresolved:
+      case ObjectAccessTargetKind.dynamic:
+      case ObjectAccessTargetKind.invalid:
+      case ObjectAccessTargetKind.missing:
         return unknownFunction;
       case ObjectAccessTargetKind.instanceMember:
         return _getFunctionType(
@@ -1172,23 +1137,95 @@
     throw unhandled('$target', 'getFunctionType', null, null);
   }
 
-  /// Returns the type of the 'key' parameter in an []= implementation.
+  /// Returns the return type of the invocation of [target] on [receiverType].
+  // TODO(johnniwinther): Cleanup [getFunctionType], [getReturnType],
+  // [getIndexKeyType] and [getIndexSetValueType]. We shouldn't need that many.
+  DartType getReturnType(ObjectAccessTarget target, DartType receiverType) {
+    switch (target.kind) {
+      case ObjectAccessTargetKind.instanceMember:
+        FunctionType functionType = _getFunctionType(
+            getGetterTypeForMemberTarget(target.member, receiverType), false);
+        return functionType.returnType;
+        break;
+      case ObjectAccessTargetKind.extensionMember:
+        switch (target.extensionMethodKind) {
+          case ProcedureKind.Operator:
+            FunctionType functionType = target.member.function.functionType;
+            DartType returnType = functionType.returnType;
+            if (functionType.typeParameters.isNotEmpty) {
+              Substitution substitution = Substitution.fromPairs(
+                  functionType.typeParameters,
+                  target.inferredExtensionTypeArguments);
+              return substitution.substituteType(returnType);
+            }
+            return returnType;
+          default:
+            throw unhandled('$target', 'getFunctionType', null, null);
+        }
+        break;
+      case ObjectAccessTargetKind.callFunction:
+      case ObjectAccessTargetKind.unresolved:
+      case ObjectAccessTargetKind.dynamic:
+      case ObjectAccessTargetKind.invalid:
+      case ObjectAccessTargetKind.missing:
+        break;
+    }
+    return const DynamicType();
+  }
+
+  DartType getPositionalParameterTypeForTarget(
+      ObjectAccessTarget target, DartType receiverType, int index) {
+    switch (target.kind) {
+      case ObjectAccessTargetKind.instanceMember:
+        FunctionType functionType = _getFunctionType(
+            getGetterTypeForMemberTarget(target.member, receiverType), false);
+        if (functionType.positionalParameters.length > index) {
+          return functionType.positionalParameters[index];
+        }
+        break;
+      case ObjectAccessTargetKind.extensionMember:
+        FunctionType functionType = target.member.function.functionType;
+        if (functionType.positionalParameters.length > index + 1) {
+          DartType keyType = functionType.positionalParameters[index + 1];
+          if (functionType.typeParameters.isNotEmpty) {
+            Substitution substitution = Substitution.fromPairs(
+                functionType.typeParameters,
+                target.inferredExtensionTypeArguments);
+            return substitution.substituteType(keyType);
+          }
+          return keyType;
+        }
+        break;
+      case ObjectAccessTargetKind.callFunction:
+      case ObjectAccessTargetKind.unresolved:
+      case ObjectAccessTargetKind.dynamic:
+      case ObjectAccessTargetKind.invalid:
+      case ObjectAccessTargetKind.missing:
+        break;
+    }
+    return const DynamicType();
+  }
+
+  /// Returns the type of the 'key' parameter in an [] or []= implementation.
   ///
   /// For instance
   ///
   ///    class Class<K, V> {
+  ///      V operator [](K key) => null;
   ///      void operator []=(K key, V value) {}
   ///    }
   ///
   ///    extension Extension<K, V> on Class<K, V> {
+  ///      V operator [](K key) => null;
   ///      void operator []=(K key, V value) {}
   ///    }
   ///
+  ///    new Class<int, String>()[0];             // The key type is `int`.
   ///    new Class<int, String>()[0] = 'foo';     // The key type is `int`.
+  ///    Extension<int, String>(null)[0];         // The key type is `int`.
   ///    Extension<int, String>(null)[0] = 'foo'; // The key type is `int`.
   ///
-  DartType getIndexSetKeyType(
-      ObjectAccessTarget target, DartType receiverType) {
+  DartType getIndexKeyType(ObjectAccessTarget target, DartType receiverType) {
     switch (target.kind) {
       case ObjectAccessTargetKind.instanceMember:
         FunctionType functionType = _getFunctionType(
@@ -1202,14 +1239,14 @@
           case ProcedureKind.Operator:
             FunctionType functionType = target.member.function.functionType;
             if (functionType.positionalParameters.length >= 2) {
-              DartType indexType = functionType.positionalParameters[1];
+              DartType keyType = functionType.positionalParameters[1];
               if (functionType.typeParameters.isNotEmpty) {
                 Substitution substitution = Substitution.fromPairs(
                     functionType.typeParameters,
                     target.inferredExtensionTypeArguments);
-                return substitution.substituteType(indexType);
+                return substitution.substituteType(keyType);
               }
-              return indexType;
+              return keyType;
             }
             break;
           default:
@@ -1218,9 +1255,12 @@
         break;
       case ObjectAccessTargetKind.callFunction:
       case ObjectAccessTargetKind.unresolved:
+      case ObjectAccessTargetKind.dynamic:
+      case ObjectAccessTargetKind.invalid:
+      case ObjectAccessTargetKind.missing:
         break;
     }
-    return const UnknownType();
+    return const DynamicType();
   }
 
   /// Returns the type of the 'value' parameter in an []= implementation.
@@ -1269,9 +1309,12 @@
         break;
       case ObjectAccessTargetKind.callFunction:
       case ObjectAccessTargetKind.unresolved:
+      case ObjectAccessTargetKind.dynamic:
+      case ObjectAccessTargetKind.invalid:
+      case ObjectAccessTargetKind.missing:
         break;
     }
-    return const UnknownType();
+    return const DynamicType();
   }
 
   FunctionType _getFunctionType(DartType calleeType, bool followCall) {
@@ -1317,6 +1360,9 @@
   DartType getSetterType(ObjectAccessTarget target, DartType receiverType) {
     switch (target.kind) {
       case ObjectAccessTargetKind.unresolved:
+      case ObjectAccessTargetKind.dynamic:
+      case ObjectAccessTargetKind.invalid:
+      case ObjectAccessTargetKind.missing:
         return const DynamicType();
       case ObjectAccessTargetKind.instanceMember:
         Member interfaceMember = target.member;
@@ -1366,6 +1412,7 @@
         // TODO(johnniwinther): Compute the right setter type.
         return const DynamicType();
       case ObjectAccessTargetKind.callFunction:
+        break;
     }
     throw unhandled(target.runtimeType.toString(), 'getSetterType', null, null);
   }
@@ -1498,20 +1545,23 @@
   /// Derived classes should override this method with logic that dispatches on
   /// the expression type and calls the appropriate specialized "infer" method.
   ExpressionInferenceResult inferExpression(
-      kernel.Expression expression, DartType typeContext, bool typeNeeded,
+      Expression expression, DartType typeContext, bool typeNeeded,
       {bool isVoidAllowed});
 
   @override
   void inferFieldInitializer(
     InferenceHelper helper,
     DartType context,
-    kernel.Expression initializer,
+    Expression initializer,
   ) {
     assert(closureContext == null);
     assert(!isTopLevel);
     this.helper = helper;
     ExpressionInferenceResult result =
         inferExpression(initializer, context, true, isVoidAllowed: true);
+    if (result.replacement != null) {
+      initializer = result.replacement;
+    }
     ensureAssignable(
         context, result.inferredType, initializer, initializer.fileOffset,
         isVoidAllowed: context is VoidType);
@@ -1624,6 +1674,7 @@
   DartType _inferInvocation(DartType typeContext, int offset,
       FunctionType calleeType, DartType returnType, Arguments arguments,
       {bool isOverloadedArithmeticOperator: false,
+      bool isBinaryOperator: false,
       DartType receiverType,
       bool skipTypeArgumentInference: false,
       bool isConst: false,
@@ -1717,7 +1768,7 @@
     });
 
     // Check for and remove duplicated named arguments.
-    List<kernel.NamedExpression> named = arguments.named;
+    List<NamedExpression> named = arguments.named;
     if (named.length == 2) {
       if (named[0].name == named[1].name) {
         String name = named[1].name;
@@ -1726,21 +1777,20 @@
                 templateDuplicatedNamedArgument.withArguments(name),
                 named[1].fileOffset,
                 name.length));
-        arguments.named = [new kernel.NamedExpression(named[1].name, error)];
+        arguments.named = [new NamedExpression(named[1].name, error)];
         formalTypes.removeLast();
         actualTypes.removeLast();
       }
     } else if (named.length > 2) {
-      Map<String, kernel.NamedExpression> seenNames =
-          <String, kernel.NamedExpression>{};
+      Map<String, NamedExpression> seenNames = <String, NamedExpression>{};
       bool hasProblem = false;
       int namedTypeIndex = arguments.positional.length;
-      List<kernel.NamedExpression> uniqueNamed = <kernel.NamedExpression>[];
-      for (kernel.NamedExpression expression in named) {
+      List<NamedExpression> uniqueNamed = <NamedExpression>[];
+      for (NamedExpression expression in named) {
         String name = expression.name;
         if (seenNames.containsKey(name)) {
           hasProblem = true;
-          kernel.NamedExpression prevNamedExpression = seenNames[name];
+          NamedExpression prevNamedExpression = seenNames[name];
           prevNamedExpression.value = helper.desugarSyntheticExpression(
               helper.buildProblem(
                   templateDuplicatedNamedArgument.withArguments(name),
@@ -1796,6 +1846,8 @@
           ensureAssignable(
               expectedType, actualType, expression, expression.fileOffset,
               isVoidAllowed: expectedType is VoidType,
+              // TODO(johnniwinther): Specialize message for operator
+              // invocations.
               template: templateArgumentTypeNotAssignable);
         }
       }
@@ -1891,11 +1943,11 @@
     // Otherwise, if `Qi` is not `_`, let `Ri` be the greatest closure of
     // `Qi[T/S]` with respect to `?`.  Otherwise, let `Ri` be `dynamic`.
     for (int i = 0; i < formals.length; i++) {
-      VariableDeclarationJudgment formal = formals[i];
-      if (VariableDeclarationJudgment.isImplicitlyTyped(formal)) {
+      VariableDeclarationImpl formal = formals[i];
+      if (VariableDeclarationImpl.isImplicitlyTyped(formal)) {
         DartType inferredType;
-        if (formalTypesFromContext[i] == coreTypes.nullClass.rawType) {
-          inferredType = coreTypes.objectClass.rawType;
+        if (formalTypesFromContext[i] == coreTypes.nullType) {
+          inferredType = coreTypes.objectRawType(library.nullable);
         } else if (formalTypesFromContext[i] != null) {
           inferredType = greatestClosure(coreTypes,
               substitution.substituteType(formalTypesFromContext[i]));
@@ -1947,8 +1999,7 @@
   }
 
   @override
-  void inferMetadata(
-      InferenceHelper helper, List<kernel.Expression> annotations) {
+  void inferMetadata(InferenceHelper helper, List<Expression> annotations) {
     if (annotations != null) {
       this.helper = helper;
       inferMetadataKeepingHelper(annotations);
@@ -1957,7 +2008,7 @@
   }
 
   @override
-  void inferMetadataKeepingHelper(List<kernel.Expression> annotations) {
+  void inferMetadataKeepingHelper(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
@@ -1999,90 +2050,75 @@
   /// Performs the core type inference algorithm for method invocations (this
   /// handles both null-aware and non-null-aware method invocations).
   ExpressionInferenceResult inferMethodInvocation(
-      kernel.Expression expression,
-      kernel.Expression receiver,
-      int fileOffset,
-      bool isImplicitCall,
-      DartType typeContext,
-      {VariableDeclaration receiverVariable,
-      MethodInvocation desugaredInvocation,
-      ObjectAccessTarget target,
-      Name methodName,
-      Arguments arguments}) {
-    assert(desugaredInvocation == null || target == null);
-    assert(desugaredInvocation != null || target != null);
+      MethodInvocationImpl node, DartType typeContext) {
     // First infer the receiver so we can look up the method that was invoked.
-    DartType receiverType;
-    if (receiver == null) {
-      receiverType = thisType;
-    } else {
-      ExpressionInferenceResult result =
-          inferExpression(receiver, const UnknownType(), true);
-      receiverType = result.inferredType;
-    }
-    receiverVariable?.type = receiverType;
-    if (desugaredInvocation != null) {
-      target = findMethodInvocationMember(receiverType, desugaredInvocation);
-      methodName = desugaredInvocation.name;
-      arguments = desugaredInvocation.arguments;
-    }
-    assert(
-        target != null,
-        "No target for ${expression} with desugared "
-        "invocation ${desugaredInvocation}.");
-    bool isOverloadedArithmeticOperator = target.isInstanceMember &&
-        target.member is Procedure &&
-        typeSchemaEnvironment.isOverloadedArithmeticOperatorAndType(
-            target.member, receiverType);
+    ExpressionInferenceResult result =
+        inferExpression(node.receiver, const UnknownType(), true);
+    DartType receiverType = result.inferredType;
+    ObjectAccessTarget target = findMethodInvocationMember(receiverType, node);
+    Name methodName = node.name;
+    Arguments arguments = node.arguments;
+    assert(target != null, "No target for ${node}.");
+    bool isOverloadedArithmeticOperator =
+        isOverloadedArithmeticOperatorAndType(target, receiverType);
     DartType calleeType = getGetterType(target, receiverType);
     FunctionType functionType =
-        getFunctionType(target, receiverType, !isImplicitCall);
+        getFunctionType(target, receiverType, !node.isImplicitCall);
 
     if (!target.isUnresolved &&
         calleeType is! DynamicType &&
-        calleeType != coreTypes.functionClass.rawType &&
+        !(calleeType is InterfaceType &&
+            calleeType.classNode == coreTypes.functionClass) &&
         identical(functionType, unknownFunction)) {
-      TreeNode parent = expression.parent;
-      kernel.Expression error = helper.wrapInProblem(expression,
+      TreeNode parent = node.parent;
+      Expression error = helper.wrapInProblem(node,
           templateInvokeNonFunction.withArguments(methodName.name), noLength);
-      parent?.replaceChild(expression, error);
+      parent?.replaceChild(node, error);
       return const ExpressionInferenceResult(const DynamicType());
     }
     MethodContravarianceCheckKind checkKind = preCheckInvocationContravariance(
-        receiver,
-        receiverType,
-        target,
-        desugaredInvocation,
-        arguments,
-        expression);
+        receiverType, target,
+        isThisReceiver: node.receiver is ThisExpression);
     StaticInvocation replacement;
     if (target.isExtensionMember) {
       replacement = transformExtensionMethodInvocation(
-          target, expression, receiver, arguments);
+          target, node, node.receiver, arguments);
       arguments = replacement.arguments;
     }
-    DartType inferredType = inferInvocation(typeContext, fileOffset,
+    DartType inferredType = inferInvocation(typeContext, node.fileOffset,
         functionType, functionType.returnType, arguments,
         isOverloadedArithmeticOperator: isOverloadedArithmeticOperator,
         receiverType: receiverType,
         isImplicitExtensionMember: target.isExtensionMember);
     if (methodName.name == '==') {
-      inferredType = coreTypes.boolClass.rawType;
+      inferredType = coreTypes.boolRawType(library.nonNullable);
     }
-    handleInvocationContravariance(checkKind, desugaredInvocation, arguments,
-        expression, inferredType, functionType, fileOffset);
-    if (isImplicitCall && target.isInstanceMember) {
+    handleInvocationContravariance(checkKind, node, arguments, node,
+        inferredType, functionType, node.fileOffset);
+    if (node.isImplicitCall && target.isInstanceMember) {
       Member member = target.member;
       if (!(member is Procedure && member.kind == ProcedureKind.Method)) {
-        TreeNode parent = expression.parent;
+        TreeNode parent = node.parent;
         Expression errorNode = helper.wrapInProblem(
-            expression,
+            node,
             templateImplicitCallOfNonMethod.withArguments(receiverType),
             noLength);
-        parent?.replaceChild(expression, errorNode);
+        parent?.replaceChild(node, errorNode);
       }
     }
+    _checkBoundsInMethodInvocation(target, receiverType, calleeType, methodName,
+        arguments, node.fileOffset);
 
+    return new ExpressionInferenceResult(inferredType, replacement);
+  }
+
+  void _checkBoundsInMethodInvocation(
+      ObjectAccessTarget target,
+      DartType receiverType,
+      DartType calleeType,
+      Name methodName,
+      Arguments arguments,
+      int fileOffset) {
     // If [arguments] were inferred, check them.
     // TODO(dmitryas): Figure out why [library] is sometimes null? Answer:
     // because top level inference never got a library. This has changed so
@@ -2119,18 +2155,66 @@
           fileOffset,
           inferred: getExplicitTypeArguments(arguments) == null);
     }
+  }
 
-    return new ExpressionInferenceResult(inferredType, replacement);
+  bool isOverloadedArithmeticOperatorAndType(
+      ObjectAccessTarget target, DartType receiverType) {
+    return target.isInstanceMember &&
+        target.member is Procedure &&
+        typeSchemaEnvironment.isOverloadedArithmeticOperatorAndType(
+            target.member, receiverType);
+  }
+
+  /// Performs the core type inference algorithm for super method invocations.
+  ExpressionInferenceResult inferSuperMethodInvocation(
+      SuperMethodInvocation expression,
+      DartType typeContext,
+      ObjectAccessTarget target) {
+    int fileOffset = expression.fileOffset;
+    Name methodName = expression.name;
+    Arguments arguments = expression.arguments;
+    DartType receiverType = thisType;
+    bool isOverloadedArithmeticOperator =
+        isOverloadedArithmeticOperatorAndType(target, receiverType);
+    DartType calleeType = getGetterType(target, receiverType);
+    FunctionType functionType = getFunctionType(target, receiverType, true);
+
+    if (!target.isUnresolved &&
+        calleeType is! DynamicType &&
+        !(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());
+    }
+    DartType inferredType = inferInvocation(typeContext, fileOffset,
+        functionType, functionType.returnType, arguments,
+        isOverloadedArithmeticOperator: isOverloadedArithmeticOperator,
+        receiverType: receiverType,
+        isImplicitExtensionMember: target.isExtensionMember);
+    if (methodName.name == '==') {
+      inferredType = coreTypes.boolRawType(library.nonNullable);
+    }
+    _checkBoundsInMethodInvocation(
+        target, receiverType, calleeType, methodName, arguments, fileOffset);
+
+    return new ExpressionInferenceResult(inferredType);
   }
 
   @override
-  void inferParameterInitializer(InferenceHelper helper,
-      kernel.Expression initializer, DartType declaredType) {
+  void 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);
     this.helper = null;
@@ -2138,13 +2222,13 @@
 
   /// 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,
-      {VariableDeclaration receiverVariable,
-      PropertyGet desugaredGet,
-      ObjectAccessTarget readTarget,
-      Name propertyName,
-      bool allowExtensionMethods: false}) {
+  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) {
@@ -2152,27 +2236,26 @@
     } else {
       ExpressionInferenceResult result =
           inferExpression(receiver, const UnknownType(), true);
+      if (result.replacement != null) {
+        receiver = result.replacement;
+      }
       receiverType = result.inferredType;
     }
-    receiverVariable?.type = receiverType;
-    propertyName ??= desugaredGet.name;
-    if (desugaredGet != null) {
-      readTarget = findInterfaceMember(receiverType, propertyName, fileOffset,
-          errorTemplate: templateUndefinedGetter,
-          expression: expression,
-          receiver: receiver,
-          includeExtensionMethods: allowExtensionMethods);
-      if (readTarget.isInstanceMember) {
-        if (instrumentation != null && receiverType == const DynamicType()) {
-          instrumentation.record(uri, desugaredGet.fileOffset, 'target',
-              new InstrumentationValueForMember(readTarget.member));
-        }
-        desugaredGet.interfaceTarget = readTarget.member;
+    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(uri, propertyGet.fileOffset, 'target',
+            new InstrumentationValueForMember(readTarget.member));
       }
+      propertyGet.interfaceTarget = readTarget.member;
     }
     DartType inferredType = getGetterType(readTarget, receiverType);
     Expression replacedExpression = handlePropertyGetContravariance(receiver,
-        readTarget, desugaredGet, expression, inferredType, fileOffset);
+        readTarget, propertyGet, expression, inferredType, fileOffset);
     Expression replacement;
     if (readTarget.isInstanceMember) {
       Member member = readTarget.member;
@@ -2183,7 +2266,7 @@
     } else if (readTarget.isExtensionMember) {
       int fileOffset = expression.fileOffset;
       switch (readTarget.extensionMethodKind) {
-        case kernel.ProcedureKind.Getter:
+        case ProcedureKind.Getter:
           expression.parent.replaceChild(
               expression,
               replacement = expression = helper.forest.createStaticInvocation(
@@ -2197,7 +2280,7 @@
                       extensionTypeArguments:
                           readTarget.inferredExtensionTypeArguments)));
           break;
-        case kernel.ProcedureKind.Method:
+        case ProcedureKind.Method:
           expression.parent.replaceChild(
               expression,
               replacement = expression = helper.forest.createStaticInvocation(
@@ -2211,14 +2294,29 @@
                       extensionTypeArguments:
                           readTarget.inferredExtensionTypeArguments)));
           break;
-        case kernel.ProcedureKind.Setter:
-        case kernel.ProcedureKind.Factory:
-        case kernel.ProcedureKind.Operator:
+        case ProcedureKind.Setter:
+        case ProcedureKind.Factory:
+        case ProcedureKind.Operator:
           unhandled('$readTarget', "inferPropertyGet", fileOffset, uri);
           break;
       }
     }
-    storeInferredType(expression, inferredType);
+    return new ExpressionInferenceResult(inferredType, replacement);
+  }
+
+  /// Performs the core type inference algorithm for super property get.
+  ExpressionInferenceResult inferSuperPropertyGet(SuperPropertyGet expression,
+      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 new ExpressionInferenceResult(inferredType, replacement);
   }
 
@@ -2290,12 +2388,9 @@
   /// boolean indicating whether an "as" check will need to be added due to
   /// contravariance.
   MethodContravarianceCheckKind preCheckInvocationContravariance(
-      Expression receiver,
-      DartType receiverType,
-      ObjectAccessTarget target,
-      MethodInvocation desugaredInvocation,
-      Arguments arguments,
-      Expression expression) {
+      DartType receiverType, ObjectAccessTarget target,
+      {bool isThisReceiver}) {
+    assert(isThisReceiver != null);
     if (target.isInstanceMember) {
       Member interfaceMember = target.member;
       if (interfaceMember is Field ||
@@ -2305,7 +2400,7 @@
         if (getType is DynamicType) {
           return MethodContravarianceCheckKind.none;
         }
-        if (receiver != null && receiver is! ThisExpression) {
+        if (!isThisReceiver) {
           if ((interfaceMember is Field &&
                   returnedTypeParametersOccurNonCovariantly(
                       interfaceMember.enclosingClass, interfaceMember.type)) ||
@@ -2316,8 +2411,7 @@
             return MethodContravarianceCheckKind.checkGetterReturn;
           }
         }
-      } else if (receiver != null &&
-          receiver is! ThisExpression &&
+      } else if (!isThisReceiver &&
           interfaceMember is Procedure &&
           returnedTypeParametersOccurNonCovariantly(
               interfaceMember.enclosingClass,
@@ -2389,7 +2483,7 @@
     for (Expression expression in arguments.positional) {
       callback(null, expression);
     }
-    for (kernel.NamedExpression namedExpression in arguments.named) {
+    for (NamedExpression namedExpression in arguments.named) {
       callback(namedExpression.name, namedExpression.value);
     }
   }
@@ -2441,8 +2535,8 @@
     }
     if (expression is VariableGet) {
       VariableDeclaration variable = expression.variable;
-      if (variable is VariableDeclarationJudgment &&
-          VariableDeclarationJudgment.isLocalFunction(variable)) {
+      if (variable is VariableDeclarationImpl &&
+          VariableDeclarationImpl.isLocalFunction(variable)) {
         return templateInvalidCastLocalFunction;
       }
     }
@@ -2621,8 +2715,12 @@
 enum ObjectAccessTargetKind {
   instanceMember,
   callFunction,
-  unresolved,
   extensionMember,
+  dynamic,
+  invalid,
+  missing,
+  // TODO(johnniwinther): Remove this.
+  unresolved,
 }
 
 /// Result for performing an access on an object, like `o.foo`, `o.foo()` and
@@ -2652,13 +2750,26 @@
   const ObjectAccessTarget.callFunction()
       : this.internal(ObjectAccessTargetKind.callFunction, null);
 
-  /// Creates an access with no target.
-  ///
-  /// Done depending on context this may or may not be an error. For instance
-  /// if the receiver has type `dynamic` this is not an error.
+  /// Creates an access with no known target.
   const ObjectAccessTarget.unresolved()
       : this.internal(ObjectAccessTargetKind.unresolved, null);
 
+  /// Creates an access on a dynamic receiver type with no known target.
+  const ObjectAccessTarget.dynamic()
+      : this.internal(ObjectAccessTargetKind.dynamic, null);
+
+  /// Creates an access with no target due to an invalid receiver type.
+  ///
+  /// This is not in itself an error but a consequence of another error.
+  const ObjectAccessTarget.invalid()
+      : this.internal(ObjectAccessTargetKind.invalid, null);
+
+  /// Creates an access with no target.
+  ///
+  /// This is an error case.
+  const ObjectAccessTarget.missing()
+      : this.internal(ObjectAccessTargetKind.missing, null);
+
   /// Returns `true` if this is an access to an instance member.
   bool get isInstanceMember => kind == ObjectAccessTargetKind.instanceMember;
 
@@ -2669,7 +2780,20 @@
   bool get isCallFunction => kind == ObjectAccessTargetKind.callFunction;
 
   /// Returns `true` if this is an access without a known target.
-  bool get isUnresolved => kind == ObjectAccessTargetKind.unresolved;
+  bool get isUnresolved =>
+      kind == ObjectAccessTargetKind.unresolved ||
+      isDynamic ||
+      isInvalid ||
+      isMissing;
+
+  /// Returns `true` if this is an access on a dynamic receiver type.
+  bool get isDynamic => kind == ObjectAccessTargetKind.dynamic;
+
+  /// Returns `true` if this is an access on an invalid receiver type.
+  bool get isInvalid => kind == ObjectAccessTargetKind.invalid;
+
+  /// Returns `true` if this is an access with no target.
+  bool get isMissing => kind == ObjectAccessTargetKind.missing;
 
   /// Returns the original procedure kind, if this is an extension method
   /// target.
@@ -2709,7 +2833,8 @@
 
   @override
   String toString() =>
-      'ExtensionAccessTarget($kind,$member,$extensionMethodKind)';
+      'ExtensionAccessTarget($kind,$member,$extensionMethodKind,'
+      '$inferredExtensionTypeArguments)';
 }
 
 class ExtensionAccessCandidate {
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 1b8cd24..e7fc374 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
@@ -58,7 +58,7 @@
   bool isLeastClosure;
 
   _TypeSchemaEliminationVisitor(CoreTypes coreTypes, this.isLeastClosure)
-      : nullType = coreTypes.nullClass.rawType;
+      : nullType = coreTypes.nullType;
 
   @override
   DartType visitFunctionType(FunctionType node) {
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 cf1097f..ad77c76 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,7 +102,7 @@
 
   InterfaceType getLegacyLeastUpperBound(
       InterfaceType type1, InterfaceType type2) {
-    return hierarchy.getLegacyLeastUpperBound(type1, type2);
+    return hierarchy.getLegacyLeastUpperBound(type1, type2, this.coreTypes);
   }
 
   /// Modify the given [constraint]'s lower bound to include [lower].
@@ -405,12 +405,12 @@
 class TypeVariableEliminator extends Substitution {
   final CoreTypes _coreTypes;
 
+  // TODO(dmitryas): Instead of a CoreTypes object pass null and an Object type
+  // explicitly, with the suitable nullability on the latter.
   TypeVariableEliminator(this._coreTypes);
 
   @override
   DartType getSubstitute(TypeParameter parameter, bool upperBound) {
-    return upperBound
-        ? _coreTypes.nullClass.rawType
-        : _coreTypes.objectClass.rawType;
+    return upperBound ? _coreTypes.nullType : _coreTypes.objectLegacyRawType;
   }
 }
diff --git a/pkg/front_end/lib/src/scanner/token.dart b/pkg/front_end/lib/src/scanner/token.dart
index d16d2d4..37a8a52 100644
--- a/pkg/front_end/lib/src/scanner/token.dart
+++ b/pkg/front_end/lib/src/scanner/token.dart
@@ -209,6 +209,8 @@
 
   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);
 
@@ -237,6 +239,8 @@
   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);
 
@@ -321,6 +325,7 @@
     IMPLEMENTS,
     IMPORT,
     IN,
+    INOUT,
     INTERFACE,
     IS,
     LATE,
@@ -332,6 +337,7 @@
     OF,
     ON,
     OPERATOR,
+    OUT,
     PART,
     PATCH,
     REQUIRED,
diff --git a/pkg/front_end/lib/src/testing/id.dart b/pkg/front_end/lib/src/testing/id.dart
index f0b323e..16fdce5 100644
--- a/pkg/front_end/lib/src/testing/id.dart
+++ b/pkg/front_end/lib/src/testing/id.dart
@@ -350,22 +350,34 @@
   /// Checks for duplicate data for [id].
   void registerValue(Uri uri, int offset, Id id, T value, Object object) {
     if (value != null) {
+      ActualData<T> newData = new ActualData<T>(id, value, uri, offset, object);
       if (actualMap.containsKey(id)) {
-        // TODO(johnniwinther): Maybe let the test supply a way to merge
-        // multiple data on the same id?
         ActualData<T> existingData = actualMap[id];
-        report(uri, offset, "Duplicate id ${id}, value=$value, object=$object");
-        report(
-            uri,
-            offset,
-            "Duplicate id ${id}, value=${existingData.value}, "
-            "object=${existingData.object}");
-        fail("Duplicate id $id.");
+        ActualData<T> mergedData = mergeData(existingData, newData);
+        if (mergedData != null) {
+          actualMap[id] = mergedData;
+        } else {
+          report(
+              uri,
+              offset,
+              "Duplicate id ${id}, value=$value, object=$object "
+              "(${object.runtimeType})");
+          report(
+              uri,
+              offset,
+              "Duplicate id ${id}, value=${existingData.value}, "
+              "object=${existingData.object} "
+              "(${existingData.object.runtimeType})");
+          fail("Duplicate id $id.");
+        }
+      } else {
+        actualMap[id] = newData;
       }
-      actualMap[id] = new ActualData<T>(id, value, uri, offset, object);
     }
   }
 
+  ActualData<T> mergeData(ActualData<T> value1, ActualData<T> value2) => null;
+
   /// Called to report duplicate errors.
   void report(Uri uri, int offset, String message);
 
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 8d11e08..5c99198 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -406,6 +406,7 @@
 NotAnLvalue/example: Fail
 NotBinaryOperator/analyzerCode: Fail
 NotConstantExpression/example: Fail
+NullAwareCascadeOutOfOrder/example: Fail
 OperatorMinusParameterMismatch/example: Fail
 OperatorParameterMismatch0/analyzerCode: Fail
 OperatorParameterMismatch0/example: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index a1b889c..0436850 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -195,6 +195,16 @@
   template: "Not a constant expression."
   analyzerCode: NOT_CONSTANT_EXPRESSION
 
+MissingExplicitConst:
+  template: "Constant expression expected."
+  tip: "Try inserting 'const'."
+  analyzerCode: NOT_CONSTANT_EXPRESSION
+  script: >
+    class A {
+      final x;
+      const A(): x = [];
+    }
+
 NonAsciiIdentifier:
   template: "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)."
@@ -1249,6 +1259,12 @@
   tip: "Try replacing '?.' with '.'"
   analyzerCode: ParserErrorCode.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER
 
+NullAwareCascadeOutOfOrder:
+  index: 96
+  template: "The '?..' cascade operator must be first in the cascade sequence."
+  tip: "Try moving the '?..' operator to be the first cascade operator in the sequence."
+  analyzerCode: ParserErrorCode.NULL_AWARE_CASCADE_OUT_OF_ORDER
+
 ConstFieldWithoutInitializer:
   template: "The const variable '#name' must be initialized."
   tip: "Try adding an initializer ('= <expression>') to the declaration."
@@ -1680,14 +1696,6 @@
   template: "Compilation aborted due to fatal '#name' at:\n#string"
   severity: INTERNAL_PROBLEM
 
-InternalProblemNoInferredTypeStored:
-  template: "There's no inferred type for '#name'."
-  severity: INTERNAL_PROBLEM
-
-InternalProblemStoringMultipleInferredTypes:
-  template: "There's already an inferred type, '#type', for '#name'."
-  severity: INTERNAL_PROBLEM
-
 InternalProblemLabelUsageInVariablesDeclaration:
   template: "Unexpected usage of label inside declaration of variables."
   severity: INTERNAL_PROBLEM
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml
index ea3f3bf..e39bb2e 100644
--- a/pkg/front_end/pubspec.yaml
+++ b/pkg/front_end/pubspec.yaml
@@ -1,17 +1,17 @@
 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.24
+version: 0.1.25
 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.24
+  kernel: 0.3.25
   package_config: '^1.1.0'
 dev_dependencies:
-  analyzer: 0.38.2
+  analyzer: 0.38.3
   args: '>=0.13.0 <2.0.0'
   build_integration:
     path: ../build_integration
diff --git a/pkg/front_end/test/dill_round_trip_test.dart b/pkg/front_end/test/dill_round_trip_test.dart
new file mode 100644
index 0000000..424a3b1
--- /dev/null
+++ b/pkg/front_end/test/dill_round_trip_test.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.
+
+import 'package:front_end/src/fasta/kernel/utils.dart' show serializeComponent;
+
+import 'package:kernel/ast.dart' show Component;
+
+import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
+
+import 'package:kernel/target/targets.dart' show NoneTarget, TargetFlags;
+
+import 'incremental_load_from_dill_test.dart'
+    show checkIsEqual, getOptions, normalCompilePlain;
+
+main() async {
+  final Uri dart2jsUrl = Uri.base.resolve("pkg/compiler/bin/dart2js.dart");
+  Stopwatch stopwatch = new Stopwatch()..start();
+  Component compiledComponent = await normalCompilePlain(dart2jsUrl,
+      options: getOptions()
+        ..target = new NoneTarget(new TargetFlags())
+        ..omitPlatform = false);
+  print("Compiled dart2js in ${stopwatch.elapsedMilliseconds} ms");
+  stopwatch.reset();
+
+  List<int> bytes = serializeComponent(compiledComponent);
+  print("Serialized dart2js in ${stopwatch.elapsedMilliseconds} ms");
+  print("Output is ${bytes.length} bytes long.");
+  print("");
+  stopwatch.reset();
+
+  print("Round-tripping with lazy disabled");
+  roundTrip(
+      new BinaryBuilder(bytes,
+          disableLazyReading: true, disableLazyClassReading: true),
+      bytes);
+
+  print("Round-tripping with lazy enabled");
+  roundTrip(
+      new BinaryBuilder(bytes,
+          disableLazyReading: false, disableLazyClassReading: false),
+      bytes);
+
+  print("OK");
+}
+
+void roundTrip(BinaryBuilder binaryBuilder, List<int> bytes) {
+  Stopwatch stopwatch = new Stopwatch()..start();
+  Component c = new Component();
+  binaryBuilder.readComponent(c);
+  List<int> bytesRoundTripped = serializeComponent(c);
+  print("Loaded and serialized in ${stopwatch.elapsedMilliseconds} ms");
+  stopwatch.reset();
+
+  checkIsEqual(bytes, bytesRoundTripped);
+  print("Checked equal in ${stopwatch.elapsedMilliseconds} ms");
+  stopwatch.reset();
+  print("");
+}
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
index 26fa4ca..b93bf2e 100644
--- a/pkg/front_end/test/fasta/flow_analysis/flow_analysis_test.dart
+++ b/pkg/front_end/test/fasta/flow_analysis/flow_analysis_test.dart
@@ -331,18 +331,31 @@
         h.declare(x, initialized: true);
         h.promote(x, 'int');
         expect(flow.promotedType(x).type, 'int');
-        flow.forEach_bodyBegin({x});
+        flow.forEach_bodyBegin({x}, null);
         expect(flow.promotedType(x), isNull);
         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({});
+        flow.forEach_bodyBegin({}, null);
         h.promote(x, 'int');
         expect(flow.promotedType(x).type, 'int');
         flow.forEach_end();
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 30206f6..273a013 100644
--- a/pkg/front_end/test/fasta/generator_to_string_test.dart
+++ b/pkg/front_end/test/fasta/generator_to_string_test.dart
@@ -73,8 +73,7 @@
         new KernelTarget(
                 null,
                 false,
-                new DillTarget(null, null,
-                    new NoneTarget(new TargetFlags(legacyMode: true))),
+                new DillTarget(null, null, new NoneTarget(new TargetFlags())),
                 null)
             .loader,
         null);
diff --git a/pkg/front_end/test/fasta/incremental_hello_test.dart b/pkg/front_end/test/fasta/incremental_hello_test.dart
index ccafee3..f7435f6 100644
--- a/pkg/front_end/test/fasta/incremental_hello_test.dart
+++ b/pkg/front_end/test/fasta/incremental_hello_test.dart
@@ -35,8 +35,7 @@
 test({bool sdkFromSource}) async {
   final CompilerOptions optionBuilder = new CompilerOptions()
     ..packagesFileUri = Uri.base.resolve(".packages")
-    ..target = new VmTarget(new TargetFlags(legacyMode: true))
-    ..legacyMode = true
+    ..target = new VmTarget(new TargetFlags())
     ..omitPlatform = true
     ..onDiagnostic = diagnosticMessageHandler
     ..environmentDefines = const {};
diff --git a/pkg/front_end/test/fasta/incremental_test.dart b/pkg/front_end/test/fasta/incremental_test.dart
index 59c2e1d..3b22af2 100644
--- a/pkg/front_end/test/fasta/incremental_test.dart
+++ b/pkg/front_end/test/fasta/incremental_test.dart
@@ -225,7 +225,6 @@
   final List<DiagnosticMessage> errors = <DiagnosticMessage>[];
 
   final CompilerOptions optionBuilder = new CompilerOptions()
-    ..legacyMode = true
     ..verbose = true
     ..fileSystem = fs
     ..sdkSummary = sdkSummary
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index 4170490..3837eea 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -131,10 +131,6 @@
 
 final Expectation runtimeError = ExpectationSet.Default["RuntimeError"];
 
-String generateExpectationName(bool legacyMode) {
-  return legacyMode ? "legacy" : "strong";
-}
-
 const String experimentalFlagOptions = '--enable-experiment=';
 
 class TestOptions {
diff --git a/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_test.dart b/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_test.dart
index 262886f..8da59a4 100644
--- a/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_test.dart
@@ -53,7 +53,7 @@
 
   Class get functionClass => coreTypes.functionClass;
 
-  InterfaceType get functionType => functionClass.rawType;
+  InterfaceType get functionType => coreTypes.functionLegacyRawType;
 
   Class get iterableClass => coreTypes.iterableClass;
 
@@ -61,15 +61,15 @@
 
   Class get mapClass => coreTypes.mapClass;
 
-  InterfaceType get nullType => coreTypes.nullClass.rawType;
+  InterfaceType get nullType => coreTypes.nullType;
 
   Class get objectClass => coreTypes.objectClass;
 
-  InterfaceType get objectType => objectClass.rawType;
+  InterfaceType get objectType => coreTypes.objectLegacyRawType;
 
-  InterfaceType get P => classP.rawType;
+  InterfaceType get P => coreTypes.legacyRawType(classP);
 
-  InterfaceType get Q => classQ.rawType;
+  InterfaceType get Q => coreTypes.legacyRawType(classQ);
 
   void test_any_subtype_parameter() {
     _checkConstraints(Q, T1, ['lib::Q* <: T1']);
@@ -180,7 +180,7 @@
   }
 
   void test_null_subtype_any() {
-    _checkConstraints(nullType, T1, ['dart.core::Null* <: T1']);
+    _checkConstraints(nullType, T1, ['dart.core::Null? <: T1']);
     _checkConstraints(nullType, Q, []);
   }
 
diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_elimination_test.dart b/pkg/front_end/test/fasta/type_inference/type_schema_elimination_test.dart
index bd78483..b6d152f 100644
--- a/pkg/front_end/test/fasta/type_inference/type_schema_elimination_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_schema_elimination_test.dart
@@ -24,9 +24,9 @@
 
   DartType get dynamicType => const DynamicType();
 
-  DartType get nullType => coreTypes.nullClass.rawType;
+  DartType get nullType => coreTypes.nullType;
 
-  DartType get objectType => coreTypes.objectClass.rawType;
+  DartType get objectType => coreTypes.objectLegacyRawType;
 
   DartType greatestClosure(DartType schema) =>
       typeSchemaElimination.greatestClosure(coreTypes, schema);
@@ -38,11 +38,11 @@
     expect(
         greatestClosure(new FunctionType([unknownType], dynamicType))
             .toString(),
-        '(dart.core::Null*) →* dynamic');
+        '(dart.core::Null?) →* dynamic');
     expect(
         greatestClosure(new FunctionType([], dynamicType,
             namedParameters: [new NamedType('foo', unknownType)])).toString(),
-        '({foo: dart.core::Null*}) →* dynamic');
+        '({foo: dart.core::Null?}) →* dynamic');
   }
 
   void test_greatestClosure_contravariant_contravariant() {
@@ -71,8 +71,8 @@
               new NamedType('a', unknownType),
               new NamedType('b', unknownType)
             ])).toString(),
-        '(dart.core::Null*, dart.core::Null*, {a: dart.core::Null*, '
-        'b: dart.core::Null*}) →* dynamic');
+        '(dart.core::Null?, dart.core::Null?, {a: dart.core::Null?, '
+        'b: dart.core::Null?}) →* dynamic');
   }
 
   void test_greatestClosure_simple() {
@@ -95,16 +95,16 @@
           new FunctionType([unknownType], dynamicType)
         ], dynamicType))
             .toString(),
-        '((dart.core::Null*) →* dynamic) →* dynamic');
+        '((dart.core::Null?) →* dynamic) →* dynamic');
   }
 
   void test_leastClosure_covariant() {
     expect(leastClosure(new FunctionType([], unknownType)).toString(),
-        '() →* dart.core::Null*');
+        '() →* dart.core::Null?');
     expect(
         leastClosure(new InterfaceType(coreTypes.listClass, [unknownType]))
             .toString(),
-        'dart.core::List<dart.core::Null*>*');
+        'dart.core::List<dart.core::Null?>*');
   }
 
   void test_leastClosure_function_multipleUnknown() {
@@ -114,11 +114,11 @@
               new NamedType('a', unknownType),
               new NamedType('b', unknownType)
             ])).toString(),
-        '(dynamic, dynamic, {a: dynamic, b: dynamic}) →* dart.core::Null*');
+        '(dynamic, dynamic, {a: dynamic, b: dynamic}) →* dart.core::Null?');
   }
 
   void test_leastClosure_simple() {
-    expect(leastClosure(unknownType).toString(), 'dart.core::Null*');
+    expect(leastClosure(unknownType).toString(), 'dart.core::Null?');
   }
 }
 
@@ -132,7 +132,12 @@
   @override
   final Class objectClass = new Class(name: 'Object');
 
+  @override
+  InterfaceType nullType;
+
   _MockCoreTypes() {
+    nullType = new InterfaceType(
+        nullClass, const <DynamicType>[], Nullability.nullable);
     new Library(Uri.parse('dart:core'),
         name: 'dart.core', classes: [listClass, nullClass, objectClass]);
   }
diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart b/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
index 101fb7f..1908a65 100644
--- a/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
@@ -39,11 +39,11 @@
     coreTypes = new CoreTypes(component);
   }
 
-  InterfaceType get doubleType => coreTypes.doubleClass.rawType;
+  InterfaceType get doubleType => coreTypes.doubleLegacyRawType;
 
-  InterfaceType get functionType => coreTypes.functionClass.rawType;
+  InterfaceType get functionType => coreTypes.functionLegacyRawType;
 
-  InterfaceType get intType => coreTypes.intClass.rawType;
+  InterfaceType get intType => coreTypes.intLegacyRawType;
 
   Class get iterableClass => coreTypes.iterableClass;
 
@@ -51,20 +51,20 @@
 
   Class get mapClass => coreTypes.mapClass;
 
-  InterfaceType get nullType => coreTypes.nullClass.rawType;
+  InterfaceType get nullType => coreTypes.nullType;
 
-  InterfaceType get numType => coreTypes.numClass.rawType;
+  InterfaceType get numType => coreTypes.numLegacyRawType;
 
   Class get objectClass => coreTypes.objectClass;
 
-  InterfaceType get objectType => objectClass.rawType;
+  InterfaceType get objectType => coreTypes.objectLegacyRawType;
 
   void test_addLowerBound() {
-    var A = _addClass(_class('A')).rawType;
-    var B =
-        _addClass(_class('B', supertype: A.classNode.asThisSupertype)).rawType;
-    var C =
-        _addClass(_class('C', supertype: A.classNode.asThisSupertype)).rawType;
+    var A = coreTypes.legacyRawType(_addClass(_class('A')));
+    var B = coreTypes.legacyRawType(
+        _addClass(_class('B', supertype: A.classNode.asThisSupertype)));
+    var C = coreTypes.legacyRawType(
+        _addClass(_class('C', supertype: A.classNode.asThisSupertype)));
     var env = _makeEnv();
     var typeConstraint = new TypeConstraint();
     expect(typeConstraint.lower, same(unknownType));
@@ -75,11 +75,13 @@
   }
 
   void test_addUpperBound() {
-    var A = _addClass(_class('A')).rawType;
-    var B =
-        _addClass(_class('B', supertype: A.classNode.asThisSupertype)).rawType;
-    var C =
-        _addClass(_class('C', supertype: A.classNode.asThisSupertype)).rawType;
+    var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
+    var B = coreTypes.rawType(
+        _addClass(_class('B', supertype: A.classNode.asThisSupertype)),
+        Nullability.legacy);
+    var C = coreTypes.rawType(
+        _addClass(_class('C', supertype: A.classNode.asThisSupertype)),
+        Nullability.legacy);
     var env = _makeEnv();
     var typeConstraint = new TypeConstraint();
     expect(typeConstraint.upper, same(unknownType));
@@ -92,16 +94,17 @@
   }
 
   void test_glb_bottom() {
-    var A = _addClass(_class('A')).rawType;
+    var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
     var env = _makeEnv();
     expect(env.getStandardLowerBound(bottomType, A), same(bottomType));
     expect(env.getStandardLowerBound(A, bottomType), same(bottomType));
   }
 
   void test_glb_function() {
-    var A = _addClass(_class('A')).rawType;
-    var B =
-        _addClass(_class('B', supertype: A.classNode.asThisSupertype)).rawType;
+    var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
+    var B = coreTypes.rawType(
+        _addClass(_class('B', supertype: A.classNode.asThisSupertype)),
+        Nullability.legacy);
     var env = _makeEnv();
     // GLB(() -> A, () -> B) = () -> B
     expect(
@@ -219,23 +222,24 @@
   }
 
   void test_glb_identical() {
-    var A = _addClass(_class('A')).rawType;
+    var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
     var env = _makeEnv();
     expect(env.getStandardLowerBound(A, A), same(A));
     expect(env.getStandardLowerBound(new InterfaceType(A.classNode), A), A);
   }
 
   void test_glb_subtype() {
-    var A = _addClass(_class('A')).rawType;
-    var B =
-        _addClass(_class('B', supertype: A.classNode.asThisSupertype)).rawType;
+    var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
+    var B = coreTypes.rawType(
+        _addClass(_class('B', supertype: A.classNode.asThisSupertype)),
+        Nullability.legacy);
     var env = _makeEnv();
     expect(env.getStandardLowerBound(A, B), same(B));
     expect(env.getStandardLowerBound(B, A), same(B));
   }
 
   void test_glb_top() {
-    var A = _addClass(_class('A')).rawType;
+    var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
     var env = _makeEnv();
     expect(env.getStandardLowerBound(dynamicType, A), same(A));
     expect(env.getStandardLowerBound(A, dynamicType), same(A));
@@ -246,15 +250,15 @@
   }
 
   void test_glb_unknown() {
-    var A = _addClass(_class('A')).rawType;
+    var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
     var env = _makeEnv();
     expect(env.getStandardLowerBound(A, unknownType), same(A));
     expect(env.getStandardLowerBound(unknownType, A), same(A));
   }
 
   void test_glb_unrelated() {
-    var A = _addClass(_class('A')).rawType;
-    var B = _addClass(_class('B')).rawType;
+    var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
+    var B = coreTypes.rawType(_addClass(_class('B')), Nullability.legacy);
     var env = _makeEnv();
     expect(env.getStandardLowerBound(A, B), same(bottomType));
   }
@@ -350,19 +354,25 @@
     // B C
     // |X|
     // D E
-    var A = _addClass(_class('A')).rawType;
-    var B =
-        _addClass(_class('B', supertype: A.classNode.asThisSupertype)).rawType;
-    var C =
-        _addClass(_class('C', supertype: A.classNode.asThisSupertype)).rawType;
-    var D = _addClass(_class('D', implementedTypes: [
-      B.classNode.asThisSupertype,
-      C.classNode.asThisSupertype
-    ])).rawType;
-    var E = _addClass(_class('E', implementedTypes: [
-      B.classNode.asThisSupertype,
-      C.classNode.asThisSupertype
-    ])).rawType;
+    var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
+    var B = coreTypes.rawType(
+        _addClass(_class('B', supertype: A.classNode.asThisSupertype)),
+        Nullability.legacy);
+    var C = coreTypes.rawType(
+        _addClass(_class('C', supertype: A.classNode.asThisSupertype)),
+        Nullability.legacy);
+    var D = coreTypes.rawType(
+        _addClass(_class('D', implementedTypes: [
+          B.classNode.asThisSupertype,
+          C.classNode.asThisSupertype
+        ])),
+        Nullability.legacy);
+    var E = coreTypes.rawType(
+        _addClass(_class('E', implementedTypes: [
+          B.classNode.asThisSupertype,
+          C.classNode.asThisSupertype
+        ])),
+        Nullability.legacy);
     var env = _makeEnv();
     expect(env.getStandardUpperBound(D, E), A);
   }
@@ -374,9 +384,10 @@
   }
 
   void test_lub_function() {
-    var A = _addClass(_class('A')).rawType;
-    var B =
-        _addClass(_class('B', supertype: A.classNode.asThisSupertype)).rawType;
+    var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
+    var B = coreTypes.rawType(
+        _addClass(_class('B', supertype: A.classNode.asThisSupertype)),
+        Nullability.legacy);
     var env = _makeEnv();
     // LUB(() -> A, () -> B) = () -> A
     expect(
@@ -490,16 +501,17 @@
   }
 
   void test_lub_identical() {
-    var A = _addClass(_class('A')).rawType;
+    var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
     var env = _makeEnv();
     expect(env.getStandardUpperBound(A, A), same(A));
     expect(env.getStandardUpperBound(new InterfaceType(A.classNode), A), A);
   }
 
   void test_lub_sameClass() {
-    var A = _addClass(_class('A')).rawType;
-    var B =
-        _addClass(_class('B', supertype: A.classNode.asThisSupertype)).rawType;
+    var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
+    var B = coreTypes.rawType(
+        _addClass(_class('B', supertype: A.classNode.asThisSupertype)),
+        Nullability.legacy);
     var env = _makeEnv();
     expect(env.getStandardUpperBound(_map(A, B), _map(B, A)), _map(A, A));
   }
@@ -513,7 +525,7 @@
   }
 
   void test_lub_top() {
-    var A = _addClass(_class('A')).rawType;
+    var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
     var env = _makeEnv();
     expect(env.getStandardUpperBound(dynamicType, A), same(dynamicType));
     expect(env.getStandardUpperBound(A, dynamicType), same(dynamicType));
@@ -549,16 +561,17 @@
   }
 
   void test_lub_unknown() {
-    var A = _addClass(_class('A')).rawType;
+    var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
     var env = _makeEnv();
     expect(env.getStandardLowerBound(A, unknownType), same(A));
     expect(env.getStandardLowerBound(unknownType, A), same(A));
   }
 
   void test_solveTypeConstraint() {
-    var A = _addClass(_class('A')).rawType;
-    var B =
-        _addClass(_class('B', supertype: A.classNode.asThisSupertype)).rawType;
+    var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
+    var B = coreTypes.rawType(
+        _addClass(_class('B', supertype: A.classNode.asThisSupertype)),
+        Nullability.legacy);
     var env = _makeEnv();
     // Solve(? <: T <: ?) => ?
     expect(env.solveTypeConstraint(_makeConstraint()), same(unknownType));
@@ -653,15 +666,19 @@
   }
 
   void test_typeSatisfiesConstraint() {
-    var A = _addClass(_class('A')).rawType;
-    var B =
-        _addClass(_class('B', supertype: A.classNode.asThisSupertype)).rawType;
-    var C =
-        _addClass(_class('C', supertype: B.classNode.asThisSupertype)).rawType;
-    var D =
-        _addClass(_class('D', supertype: C.classNode.asThisSupertype)).rawType;
-    var E =
-        _addClass(_class('E', supertype: D.classNode.asThisSupertype)).rawType;
+    var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
+    var B = coreTypes.rawType(
+        _addClass(_class('B', supertype: A.classNode.asThisSupertype)),
+        Nullability.legacy);
+    var C = coreTypes.rawType(
+        _addClass(_class('C', supertype: B.classNode.asThisSupertype)),
+        Nullability.legacy);
+    var D = coreTypes.rawType(
+        _addClass(_class('D', supertype: C.classNode.asThisSupertype)),
+        Nullability.legacy);
+    var E = coreTypes.rawType(
+        _addClass(_class('E', supertype: D.classNode.asThisSupertype)),
+        Nullability.legacy);
     var env = _makeEnv();
     var typeConstraint = _makeConstraint(upper: B, lower: D);
     expect(env.typeSatisfiesConstraint(A, typeConstraint), isFalse);
@@ -672,13 +689,13 @@
   }
 
   void test_unknown_at_bottom() {
-    var A = _addClass(_class('A')).rawType;
+    var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
     var env = _makeEnv();
     expect(env.isSubtypeOf(unknownType, A), isTrue);
   }
 
   void test_unknown_at_top() {
-    var A = _addClass(_class('A')).rawType;
+    var A = coreTypes.rawType(_addClass(_class('A')), Nullability.legacy);
     var env = _makeEnv();
     expect(env.isSubtypeOf(A, unknownType), isTrue);
   }
diff --git a/pkg/front_end/test/fasta/types/fasta_legacy_upper_bound_test.dart b/pkg/front_end/test/fasta/types/fasta_legacy_upper_bound_test.dart
index dec96a2..289f047 100644
--- a/pkg/front_end/test/fasta/types/fasta_legacy_upper_bound_test.dart
+++ b/pkg/front_end/test/fasta/types/fasta_legacy_upper_bound_test.dart
@@ -48,12 +48,12 @@
     await target.buildOutlines();
     ClassBuilder objectClass =
         loader.coreLibrary.lookupLocalMember("Object", required: true);
-    hierarchy = new ClassHierarchyBuilder(
-        objectClass, loader, new CoreTypes(component));
+    hierarchy = new ClassHierarchyBuilder(objectClass, loader, coreTypes);
   }
 
   @override
-  DartType getLegacyLeastUpperBound(DartType a, DartType b) {
+  DartType getLegacyLeastUpperBound(
+      DartType a, DartType b, CoreTypes coreTypes) {
     return hierarchy.getKernelLegacyLeastUpperBound(a, b);
   }
 }
diff --git a/pkg/front_end/test/fasta/types/kernel_legacy_upper_bound_test.dart b/pkg/front_end/test/fasta/types/kernel_legacy_upper_bound_test.dart
index 9004191..da6a0ad 100644
--- a/pkg/front_end/test/fasta/types/kernel_legacy_upper_bound_test.dart
+++ b/pkg/front_end/test/fasta/types/kernel_legacy_upper_bound_test.dart
@@ -8,6 +8,8 @@
 
 import "package:kernel/class_hierarchy.dart" show ClassHierarchy;
 
+import "package:kernel/core_types.dart" show CoreTypes;
+
 class KernelLegacyUpperBoundTest extends LegacyUpperBoundTest {
   ClassHierarchy hierarchy;
 
@@ -19,8 +21,9 @@
   }
 
   @override
-  DartType getLegacyLeastUpperBound(DartType a, DartType b) {
-    return hierarchy.getLegacyLeastUpperBound(a, b);
+  DartType getLegacyLeastUpperBound(
+      DartType a, DartType b, CoreTypes coreTypes) {
+    return hierarchy.getLegacyLeastUpperBound(a, b, coreTypes);
   }
 }
 
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 4d47cf6..4a7f3b8 100644
--- a/pkg/front_end/test/fasta/types/kernel_type_parser.dart
+++ b/pkg/front_end/test/fasta/types/kernel_type_parser.dart
@@ -336,7 +336,7 @@
       TypeParameter typeParameter = typeParameters[i];
       if (bound == null) {
         typeParameter
-          ..bound = objectClass.rawType
+          ..bound = new InterfaceType(objectClass)
           ..defaultType = const DynamicType();
       } else {
         DartType type =
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 1a6c955..7b13fe0 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
@@ -8,6 +8,8 @@
 
 import "package:kernel/ast.dart" show Class, Component, DartType, InterfaceType;
 
+import "package:kernel/core_types.dart";
+
 import "package:kernel/library_index.dart" show LibraryIndex;
 
 import "kernel_type_parser.dart" as kernel_type_parser show parseComponent;
@@ -17,20 +19,23 @@
 abstract class LegacyUpperBoundTest {
   Component component;
 
+  CoreTypes coreTypes;
+
   LibraryIndex index;
 
-  DartType get objectType => getCoreClass("Object").rawType;
+  DartType get objectType => coreTypes.objectLegacyRawType;
 
-  DartType get intType => getCoreClass("int").rawType;
+  DartType get intType => coreTypes.intLegacyRawType;
 
-  DartType get stringType => getCoreClass("String").rawType;
+  DartType get stringType => coreTypes.intLegacyRawType;
 
-  DartType get doubleType => getCoreClass("double").rawType;
+  DartType get doubleType => coreTypes.doubleLegacyRawType;
 
-  DartType get boolType => getCoreClass("bool").rawType;
+  DartType get boolType => coreTypes.boolLegacyRawType;
 
   void parseComponent(String source) {
     component = kernel_type_parser.parseComponent(source, libraryUri);
+    coreTypes = new CoreTypes(component);
     index = new LibraryIndex.all(component);
   }
 
@@ -42,11 +47,12 @@
     return index.getClass("dart:core", name);
   }
 
-  DartType getLegacyLeastUpperBound(DartType a, DartType b);
+  DartType getLegacyLeastUpperBound(
+      DartType a, DartType b, CoreTypes coreTypes);
 
   void checkGetLegacyLeastUpperBound(
       DartType a, DartType b, DartType expected) {
-    DartType actual = getLegacyLeastUpperBound(a, b);
+    DartType actual = getLegacyLeastUpperBound(a, b, coreTypes);
     Expect.equals(expected, actual);
   }
 
@@ -125,9 +131,9 @@
         new InterfaceType(d, [boolType, doubleType]),
         new InterfaceType(c, [doubleType]));
     checkGetLegacyLeastUpperBound(new InterfaceType(d, [intType, doubleType]),
-        new InterfaceType(d, [boolType, intType]), a.rawType);
-    checkGetLegacyLeastUpperBound(
-        e.rawType, f.rawType, new InterfaceType(b, [intType]));
+        new InterfaceType(d, [boolType, intType]), coreTypes.legacyRawType(a));
+    checkGetLegacyLeastUpperBound(coreTypes.legacyRawType(e),
+        coreTypes.legacyRawType(f), new InterfaceType(b, [intType]));
   }
 
   Future<void> test_getLegacyLeastUpperBound_nonGeneric() async {
@@ -152,13 +158,21 @@
     Class h = getClass("H");
     Class i = getClass("I");
 
-    checkGetLegacyLeastUpperBound(a.rawType, b.rawType, objectType);
-    checkGetLegacyLeastUpperBound(a.rawType, objectType, objectType);
-    checkGetLegacyLeastUpperBound(objectType, b.rawType, objectType);
-    checkGetLegacyLeastUpperBound(c.rawType, d.rawType, a.rawType);
-    checkGetLegacyLeastUpperBound(c.rawType, a.rawType, a.rawType);
-    checkGetLegacyLeastUpperBound(a.rawType, d.rawType, a.rawType);
-    checkGetLegacyLeastUpperBound(f.rawType, g.rawType, a.rawType);
-    checkGetLegacyLeastUpperBound(h.rawType, i.rawType, a.rawType);
+    checkGetLegacyLeastUpperBound(
+        coreTypes.legacyRawType(a), coreTypes.legacyRawType(b), objectType);
+    checkGetLegacyLeastUpperBound(
+        coreTypes.legacyRawType(a), objectType, objectType);
+    checkGetLegacyLeastUpperBound(
+        objectType, coreTypes.legacyRawType(b), objectType);
+    checkGetLegacyLeastUpperBound(coreTypes.legacyRawType(c),
+        coreTypes.legacyRawType(d), coreTypes.legacyRawType(a));
+    checkGetLegacyLeastUpperBound(coreTypes.legacyRawType(c),
+        coreTypes.legacyRawType(a), coreTypes.legacyRawType(a));
+    checkGetLegacyLeastUpperBound(coreTypes.legacyRawType(a),
+        coreTypes.legacyRawType(d), coreTypes.legacyRawType(a));
+    checkGetLegacyLeastUpperBound(coreTypes.legacyRawType(f),
+        coreTypes.legacyRawType(g), coreTypes.legacyRawType(a));
+    checkGetLegacyLeastUpperBound(coreTypes.legacyRawType(h),
+        coreTypes.legacyRawType(i), coreTypes.legacyRawType(a));
   }
 }
diff --git a/pkg/front_end/test/fasta/unlinked_scope_test.dart b/pkg/front_end/test/fasta/unlinked_scope_test.dart
index 05a25dc..d9eea6f 100644
--- a/pkg/front_end/test/fasta/unlinked_scope_test.dart
+++ b/pkg/front_end/test/fasta/unlinked_scope_test.dart
@@ -51,8 +51,8 @@
             new KernelTarget(
                     null,
                     false,
-                    new DillTarget(null, null,
-                        new NoneTarget(new TargetFlags(legacyMode: true))),
+                    new DillTarget(
+                        null, null, new NoneTarget(new TargetFlags())),
                     null)
                 .loader,
             null);
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
index 57a41f8..7276903 100644
--- 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
@@ -33,9 +33,33 @@
   /*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/hot_reload_e2e_test.dart b/pkg/front_end/test/hot_reload_e2e_test.dart
index 2b10afd..cda1f76 100644
--- a/pkg/front_end/test/hot_reload_e2e_test.dart
+++ b/pkg/front_end/test/hot_reload_e2e_test.dart
@@ -301,7 +301,6 @@
   var options = new CompilerOptions()
     ..sdkRoot = sdkRoot
     ..librariesSpecificationUri = Uri.base.resolve("sdk/lib/libraries.json")
-    ..legacyMode = true
     ..fileSystem = fs;
   return new IncrementalKernelGenerator(options, entryUri);
 }
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 f1469a1..2b16989 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
@@ -84,7 +84,7 @@
     bool initializeResult = await initializedCompile(
         dart2jsUrl, fullDillFromInitialized, initializeWith, [invalidateUri],
         options: getOptions()..target = new NoneTarget(new TargetFlags()));
-    Expect.equals(initializeResult, initializeExpect);
+    Expect.equals(initializeExpect, initializeResult);
     print("Initialized compile(s) from ${initializeWith.pathSegments.last} "
         "took ${stopwatch.elapsedMilliseconds} ms");
 
diff --git a/pkg/front_end/test/incremental_load_from_dill_test.dart b/pkg/front_end/test/incremental_load_from_dill_test.dart
index d258364..dd6bf04 100644
--- a/pkg/front_end/test/incremental_load_from_dill_test.dart
+++ b/pkg/front_end/test/incremental_load_from_dill_test.dart
@@ -839,14 +839,20 @@
 
 Future<Component> normalCompileToComponent(Uri input,
     {CompilerOptions options, IncrementalCompiler compiler}) async {
-  options ??= getOptions();
-  compiler ??= new TestIncrementalCompiler(options, input);
-  Component component = await compiler.computeDelta();
+  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 {
diff --git a/pkg/front_end/test/lint_test.status b/pkg/front_end/test/lint_test.status
index f7c20bf..f943795 100644
--- a/pkg/front_end/test/lint_test.status
+++ b/pkg/front_end/test/lint_test.status
@@ -9,7 +9,6 @@
 src/fasta/incremental_compiler/ImportsTwice: Fail
 src/fasta/kernel/body_builder/ImportsTwice: Fail
 src/fasta/kernel/expression_generator_helper/ImportsTwice: Fail
-src/fasta/kernel/kernel_shadow_ast/ImportsTwice: Fail
 src/fasta/parser/parser/ImportsTwice: Fail
 src/fasta/scanner/abstract_scanner/ImportsTwice: Fail
 src/fasta/scanner/recover/ImportsTwice: Fail
diff --git a/pkg/front_end/test/scanner_test.dart b/pkg/front_end/test/scanner_test.dart
index bd3ab0a..8f9700e 100644
--- a/pkg/front_end/test/scanner_test.dart
+++ b/pkg/front_end/test/scanner_test.dart
@@ -544,6 +544,16 @@
     _assertKeywordToken("in");
   }
 
+  void test_keyword_inout() {
+    _assertKeywordToken("inout",
+        configuration: ScannerConfiguration(enableVariance: true));
+  }
+
+  void test_keyword_inout_old() {
+    _assertNotKeywordToken("inout",
+        configuration: ScannerConfiguration(enableVariance: false));
+  }
+
   void test_keyword_is() {
     _assertKeywordToken("is");
   }
@@ -590,6 +600,16 @@
     _assertKeywordToken("operator");
   }
 
+  void test_keyword_out() {
+    _assertKeywordToken("out",
+        configuration: ScannerConfiguration(enableVariance: true));
+  }
+
+  void test_keyword_out_old() {
+    _assertNotKeywordToken("out",
+        configuration: ScannerConfiguration(enableVariance: false));
+  }
+
   void test_keyword_part() {
     _assertKeywordToken("part");
   }
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 7a131c6..893e05d 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -102,6 +102,7 @@
 bypassing
 c
 caches
+calculations
 callee
 caller's
 callers
@@ -229,6 +230,8 @@
 dijkstra's
 directed
 directions
+dirtify
+dirtifying
 dirty
 disallow
 disambiguator
@@ -302,6 +305,7 @@
 fff
 ffff
 fffff
+ffffffff
 ffi
 file's
 filenames
@@ -638,6 +642,8 @@
 reassigned
 rebind
 rebuild
+recalculating
+recalculation
 recall
 received
 recompiled
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index f27e950..00968fa 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -683,6 +683,7 @@
 delegates
 delegation
 delete
+deleted
 deliberately
 delimited
 delimiter
@@ -914,6 +915,7 @@
 escaped
 escapes
 escaping
+especially
 essence
 essentials
 etc
@@ -1353,6 +1355,7 @@
 inlining
 inner
 innermost
+inout
 input
 inputs
 insert
@@ -2147,6 +2150,7 @@
 really
 reason
 reasonable
+reasoning
 reasons
 receive
 receiver
@@ -2307,6 +2311,7 @@
 retype
 reuse
 reused
+reuses
 reusing
 reverse
 reversed
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 6786412..22cb2ac 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -210,6 +210,7 @@
 lc
 ld
 le
+lengths
 lightly
 likewise
 linebreaks
@@ -312,6 +313,7 @@
 shipped
 shot
 signalled
+somehow
 spans
 spell
 spellcheck
@@ -350,6 +352,8 @@
 trigger
 triggers
 trimming
+tripped
+tripping
 trivially
 truncated
 tt
diff --git a/pkg/front_end/test/split_dill_test.dart b/pkg/front_end/test/split_dill_test.dart
new file mode 100644
index 0000000..828dae4
--- /dev/null
+++ b/pkg/front_end/test/split_dill_test.dart
@@ -0,0 +1,99 @@
+// 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, File, Platform, Process, ProcessResult;
+
+import 'dart:typed_data' show Uint8List;
+
+import 'package:front_end/src/fasta/kernel/utils.dart' show serializeComponent;
+
+import 'package:kernel/ast.dart' show Component, Library;
+
+import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
+
+import 'package:kernel/target/targets.dart' show TargetFlags;
+
+import "package:vm/target/vm.dart" show VmTarget;
+
+import 'incremental_load_from_dill_test.dart'
+    show getOptions, normalCompileToComponent;
+
+import 'utils/io_utils.dart' show computeRepoDir;
+
+main() async {
+  final Uri dart2jsUrl = Uri.base.resolve("pkg/compiler/bin/dart2js.dart");
+  Stopwatch stopwatch = new Stopwatch()..start();
+  Component component = await normalCompileToComponent(dart2jsUrl,
+      options: getOptions()
+        ..target = new VmTarget(new TargetFlags())
+        ..omitPlatform = false);
+  print("Compiled dart2js in ${stopwatch.elapsedMilliseconds} ms");
+
+  component.computeCanonicalNames();
+
+  stopwatch.reset();
+  List<List<int>> libComponents = new List<List<int>>();
+  for (Library lib in component.libraries) {
+    Component libComponent = new Component(nameRoot: component.root);
+    libComponent.libraries.add(lib);
+    libComponent.uriToSource.addAll(component.uriToSource);
+    libComponent.mainMethod = component.mainMethod;
+    libComponents.add(serializeComponent(libComponent));
+  }
+  print("Serialized ${libComponents.length} separate library components "
+      "in ${stopwatch.elapsedMilliseconds} ms");
+
+  stopwatch.reset();
+  int totalLength = 0;
+  for (List<int> libComponent in libComponents) {
+    totalLength += libComponent.length;
+  }
+  Uint8List combined = new Uint8List(totalLength);
+  int index = 0;
+  for (List<int> libComponent in libComponents) {
+    combined.setRange(index, index + libComponent.length, libComponent);
+    index += libComponent.length;
+  }
+  print("Combined in ${stopwatch.elapsedMilliseconds} ms");
+
+  stopwatch.reset();
+  Component combinedComponent = new Component();
+  new BinaryBuilder(combined).readComponent(combinedComponent);
+  print("Read combined in ${stopwatch.elapsedMilliseconds} ms");
+
+  stopwatch.reset();
+  Uint8List merged = serializeComponent(combinedComponent);
+  print("Serialized combined component in ${stopwatch.elapsedMilliseconds} ms");
+
+  for (Uint8List data in [combined, merged]) {
+    stopwatch.reset();
+    Directory out = Directory.systemTemp.createTempSync("split_dill_test");
+    try {
+      File f = new File.fromUri(out.uri.resolve("out.dill"));
+      f.writeAsBytesSync(data);
+
+      ProcessResult result = await Process.run(
+          dartVm,
+          [
+            "--compile_all",
+            f.path,
+            "-h",
+          ],
+          workingDirectory: out.path);
+      print("stdout: ${result.stdout}");
+      print("stderr: ${result.stderr}");
+      print("Exit code: ${result.exitCode}");
+      if (result.exitCode != 0) {
+        throw "Got exit code ${result.exitCode}";
+      }
+      print("Ran VM on dill in ${stopwatch.elapsedMilliseconds} ms");
+    } finally {
+      out.deleteSync(recursive: true);
+    }
+  }
+}
+
+final String repoDir = computeRepoDir();
+
+String get dartVm => Platform.resolvedExecutable;
diff --git a/pkg/front_end/test/static_types/data/null_aware_for_in.dart b/pkg/front_end/test/static_types/data/null_aware_for_in.dart
new file mode 100644
index 0000000..56ea80b
--- /dev/null
+++ b/pkg/front_end/test/static_types/data/null_aware_for_in.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 Class {}
+
+main() {
+  var o;
+  // ignore: unused_local_variable
+  /*as: Class*/ for (Class c
+      in /*as: Iterable<dynamic>*/ /*dynamic*/ o?. /*dynamic*/ iterable) {}
+}
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 5a0f1f2..0014368 100644
--- a/pkg/front_end/test/static_types/static_type_test.dart
+++ b/pkg/front_end/test/static_types/static_type_test.dart
@@ -58,4 +58,16 @@
     }
     return null;
   }
+
+  ActualData<String> mergeData(
+      ActualData<String> value1, ActualData<String> value2) {
+    if (value1.object is NullLiteral && value2.object is! NullLiteral) {
+      // Skip `null` literals from null-aware operations.
+      return value2;
+    } else if (value1.object is! NullLiteral && value2.object is NullLiteral) {
+      // Skip `null` literals from null-aware operations.
+      return value1;
+    }
+    return null;
+  }
 }
diff --git a/pkg/front_end/test/token_test.dart b/pkg/front_end/test/token_test.dart
index dda8af0..cef530f 100644
--- a/pkg/front_end/test/token_test.dart
+++ b/pkg/front_end/test/token_test.dart
@@ -171,9 +171,11 @@
       Keyword.AWAIT,
       Keyword.FUNCTION,
       Keyword.HIDE,
+      Keyword.INOUT,
       Keyword.NATIVE,
       Keyword.OF,
       Keyword.ON,
+      Keyword.OUT,
       Keyword.PATCH,
       Keyword.SHOW,
       Keyword.SOURCE,
diff --git a/pkg/front_end/test/utils/kernel_chain.dart b/pkg/front_end/test/utils/kernel_chain.dart
index fca8792..7b44127 100644
--- a/pkg/front_end/test/utils/kernel_chain.dart
+++ b/pkg/front_end/test/utils/kernel_chain.dart
@@ -35,8 +35,6 @@
 
 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;
@@ -333,11 +331,7 @@
     File generated = new File.fromUri(uri);
     IOSink sink = generated.openWrite();
     try {
-      try {
-        new BinaryPrinter(sink).writeComponentFile(component);
-      } finally {
-        component.unbindCanonicalNames();
-      }
+      new BinaryPrinter(sink).writeComponentFile(component);
     } catch (e, s) {
       return fail(uri, e, s);
     } finally {
@@ -363,21 +357,6 @@
   }
 }
 
-class Copy extends Step<Component, Component, ChainContext> {
-  const Copy();
-
-  String get name => "copy component";
-
-  Future<Result<Component>> run(Component component, _) async {
-    BytesCollector sink = new BytesCollector();
-    new BinaryPrinter(sink).writeComponentFile(component);
-    component.unbindCanonicalNames();
-    Uint8List bytes = sink.collect();
-    new BinaryBuilder(bytes).readComponent(component);
-    return pass(component);
-  }
-}
-
 class BytesCollector implements Sink<List<int>> {
   final List<List<int>> lists = <List<int>>[];
 
diff --git a/pkg/front_end/test/utils/validating_instrumentation.dart b/pkg/front_end/test/utils/validating_instrumentation.dart
index afdda22..741876c 100644
--- a/pkg/front_end/test/utils/validating_instrumentation.dart
+++ b/pkg/front_end/test/utils/validating_instrumentation.dart
@@ -194,7 +194,7 @@
         _Expectation expectation = expectationsAtOffset[i];
         if (expectation.property == property) {
           if (!value.matches(expectation.value)) {
-            _problemWithStack(
+            _problem(
                 uri,
                 offset,
                 'expected $property=${expectation.value}, got '
@@ -209,7 +209,7 @@
     }
     // Unexpected property/value pair.  See if we should report.
     if (_shouldCheck(property, uri, offset)) {
-      _problemWithStack(
+      _problem(
           uri,
           offset,
           'expected nothing, got $property=${value.toString()}',
@@ -273,6 +273,7 @@
     _fixes.putIfAbsent(uri, () => []).add(fix);
   }
 
+  /// ignore: unused_element
   void _problemWithStack(Uri uri, int offset, String desc, _Fix fix) {
     _problems.add(_formatProblem(uri, offset, desc, StackTrace.current));
     _fixes.putIfAbsent(uri, () => []).add(fix);
diff --git a/pkg/front_end/testcases/dartino/add_static_field.incremental.yaml b/pkg/front_end/testcases/dartino/add_static_field.incremental.yaml
index e552e1a..6dee955 100644
--- a/pkg/front_end/testcases/dartino/add_static_field.incremental.yaml
+++ b/pkg/front_end/testcases/dartino/add_static_field.incremental.yaml
@@ -15,7 +15,7 @@
     print("v1");
   ====
     print(C.field);
-    field = "value";
+    C.field = "value";
     print(C.field);
   >>>>
   }
diff --git a/pkg/front_end/testcases/dartino/add_static_method.incremental.yaml b/pkg/front_end/testcases/dartino/add_static_method.incremental.yaml
index 4a45a2b..1874341 100644
--- a/pkg/front_end/testcases/dartino/add_static_method.incremental.yaml
+++ b/pkg/front_end/testcases/dartino/add_static_method.incremental.yaml
@@ -6,7 +6,7 @@
   // Test that static methods can be added
 
   class C {
-  <<<< "threw"
+  <<<< "v1"
   ==== "v2"
     static foo() {
       print('v2');
@@ -15,10 +15,9 @@
   }
 
   main() {
-    new C(); // TODO(ahe): Work around dart2js assertion in World.subclassesOf
-    try {
+  <<<<
+    print("v1");
+  ====
       C.foo();
-    } catch(e) {
-      print('threw');
-    }
+  >>>>
   }
diff --git a/pkg/front_end/testcases/dartino/add_top_level_method.incremental.yaml b/pkg/front_end/testcases/dartino/add_top_level_method.incremental.yaml
index 7d3f08c..4c7b3e8 100644
--- a/pkg/front_end/testcases/dartino/add_top_level_method.incremental.yaml
+++ b/pkg/front_end/testcases/dartino/add_top_level_method.incremental.yaml
@@ -5,16 +5,15 @@
 main.dart.patch: |
   // Test that top-level functions can be added
 
-  <<<< "threw"
+  <<<< []
   ==== "v2"
   foo() {
     print('v2');
   }
   >>>>
   main() {
-    try {
+  <<<<
+  ====
       foo();
-    } catch(e) {
-      print('threw');
-    }
+  >>>>
   }
diff --git a/pkg/front_end/testcases/dartino/bad_diagnostics.incremental.yaml b/pkg/front_end/testcases/dartino/bad_diagnostics.incremental.yaml
index b84bac2..259f494 100644
--- a/pkg/front_end/testcases/dartino/bad_diagnostics.incremental.yaml
+++ b/pkg/front_end/testcases/dartino/bad_diagnostics.incremental.yaml
@@ -6,7 +6,7 @@
   // Test that our diagnostics handler doesn't crash
   main() {
   <<<< []
-  ==== []
+  ==== {"messages":[],"hasCompileTimeError":1}
     // This is a long comment to guarantee that we have a position beyond the end
     // of the first version of this file.
     NoSuchClass c = null; // Provoke a warning to exercise the diagnostic handler.
diff --git a/pkg/front_end/testcases/dartino/compile_time_error_006.incremental.yaml b/pkg/front_end/testcases/dartino/compile_time_error_006.incremental.yaml
index eda61f0..c0a306c 100644
--- a/pkg/front_end/testcases/dartino/compile_time_error_006.incremental.yaml
+++ b/pkg/front_end/testcases/dartino/compile_time_error_006.incremental.yaml
@@ -3,16 +3,15 @@
 # BSD-style license that can be found in the LICENSE.md file.
 
 main.dart.patch: |
-  <<<< "error"
+  <<<< []
   ==== {"messages":[],"hasCompileTimeError":1}
   test({b}) {
     if (?b) return b;
   }
   >>>>
   main() {
-    try {
-      test(b: 2);
-    } catch (e) {
-      print("error");
-    }
+  <<<<
+  ====
+    test(b: 2);
+  >>>>
   }
diff --git a/pkg/front_end/testcases/dartino/instance_field_to_static_field.incremental.yaml b/pkg/front_end/testcases/dartino/instance_field_to_static_field.incremental.yaml
index fa6f56b..aeb652c 100644
--- a/pkg/front_end/testcases/dartino/instance_field_to_static_field.incremental.yaml
+++ b/pkg/front_end/testcases/dartino/instance_field_to_static_field.incremental.yaml
@@ -6,14 +6,14 @@
   // Test that instance field can be made static
 
   class C {
-  <<<< ["[instance] is null","[C.x] threw","v1"]
-    int x;
+  <<<< {"messages":[],"hasCompileTimeError":1}
+    String x;
   ==== ["v2","[instance.x] threw"]
-    static int x;
+    static String x;
   >>>>
   }
 
-  var instance;
+  dynamic instance;
 
   main() {
     if (instance == null) {
diff --git a/pkg/front_end/testcases/dartino/remove_class.incremental.yaml b/pkg/front_end/testcases/dartino/remove_class.incremental.yaml
index f0218de..618a7a3 100644
--- a/pkg/front_end/testcases/dartino/remove_class.incremental.yaml
+++ b/pkg/front_end/testcases/dartino/remove_class.incremental.yaml
@@ -8,13 +8,9 @@
   <<<< "v1"
   class C {
   }
-  ==== {"messages":["v2"]}
+  ==== {"messages":[],"hasCompileTimeError":1}
   >>>>
   main() {
-    try {
-      new C();
-      print('v1');
-    } catch (e) {
-      print('v2');
-    }
+    new C();
+    print('v1');
   }
diff --git a/pkg/front_end/testcases/dartino/remove_class_with_static_method.incremental.yaml b/pkg/front_end/testcases/dartino/remove_class_with_static_method.incremental.yaml
index 1ed4752..a687de8 100644
--- a/pkg/front_end/testcases/dartino/remove_class_with_static_method.incremental.yaml
+++ b/pkg/front_end/testcases/dartino/remove_class_with_static_method.incremental.yaml
@@ -11,12 +11,9 @@
       print('v1');
     }
   }
-  ==== "v2"
+  ==== {"messages":[],"hasCompileTimeError":1}
   >>>>
   main() {
-    try {
-      C.m();
-    } catch (e) {
-      print('v2');
-    }
+    C.m();
+    print('v2');
   }
diff --git a/pkg/front_end/testcases/dartino/remove_instance_method_stored_in_tearoff.incremental.yaml b/pkg/front_end/testcases/dartino/remove_instance_method_stored_in_tearoff.incremental.yaml
index 39f252c..4db42fd 100644
--- a/pkg/front_end/testcases/dartino/remove_instance_method_stored_in_tearoff.incremental.yaml
+++ b/pkg/front_end/testcases/dartino/remove_instance_method_stored_in_tearoff.incremental.yaml
@@ -10,7 +10,7 @@
     m() {
       print('v1');
     }
-  ==== {"messages":["threw", "threw"]}
+  ==== {"messages":[],"hasCompileTimeError":1}
   >>>>
   }
   var closure;
@@ -19,15 +19,5 @@
       print('instance is null');
       closure = new C().m;
     }
-    try {
-      closure();
-    } catch (e) {
-      print('threw');
-    }
-
-    try {
-      new C().m;
-    } catch (e) {
-      print("threw");
-    }
+    closure();
   }
diff --git a/pkg/front_end/testcases/dartino/remove_instance_method_with_optional_parameters_stored_in_tearoff.incremental.yaml b/pkg/front_end/testcases/dartino/remove_instance_method_with_optional_parameters_stored_in_tearoff.incremental.yaml
index 21c855e..ff69c99 100644
--- a/pkg/front_end/testcases/dartino/remove_instance_method_with_optional_parameters_stored_in_tearoff.incremental.yaml
+++ b/pkg/front_end/testcases/dartino/remove_instance_method_with_optional_parameters_stored_in_tearoff.incremental.yaml
@@ -11,7 +11,7 @@
     m([a = "a"]) {
       print('v1');
     }
-  ==== ["threw", "threw"]
+  ==== {"messages":[],"hasCompileTimeError":1}
   >>>>
   }
   var closure;
@@ -20,14 +20,6 @@
       print('closure is null');
       closure = new C().m;
     }
-    try {
-      closure();
-    } catch (e) {
-      print('threw');
-    }
-      try {
-      closure("b");
-    } catch (e) {
-      print('threw');
-    }
+    closure();
+    closure("b");
   }
diff --git a/pkg/front_end/testcases/dartino/remove_static_method.incremental.yaml b/pkg/front_end/testcases/dartino/remove_static_method.incremental.yaml
index aeb8ca6..f82093b 100644
--- a/pkg/front_end/testcases/dartino/remove_static_method.incremental.yaml
+++ b/pkg/front_end/testcases/dartino/remove_static_method.incremental.yaml
@@ -10,11 +10,11 @@
     static staticMethod() {
       print('v1');
     }
-  ==== "threw"
+  ==== {"messages":[],"hasCompileTimeError":1}
   >>>>
   }
   class C {
-    m() {
+    m(dynamic o) {
       try {
         B.staticMethod();
       } catch (e) {
@@ -23,7 +23,7 @@
       try {
         // Ensure that noSuchMethod support is compiled. This test is not about
         // adding new classes.
-        B.missingMethod();
+        o.missingMethod();
         print('bad');
       } catch (e) {
       }
@@ -31,10 +31,9 @@
   }
   var instance;
   main() {
-    new B(); // TODO(ahe): Work around dart2js assertion in World.subclassesOf
     if (instance == null) {
       print('instance is null');
       instance = new C();
     }
-    instance.m();
+    instance.m(new B());
   }
diff --git a/pkg/front_end/testcases/dartino/remove_top_level_method.incremental.yaml b/pkg/front_end/testcases/dartino/remove_top_level_method.incremental.yaml
index 5b10cc6..cc671ce 100644
--- a/pkg/front_end/testcases/dartino/remove_top_level_method.incremental.yaml
+++ b/pkg/front_end/testcases/dartino/remove_top_level_method.incremental.yaml
@@ -9,15 +9,11 @@
   toplevel() {
     print('v1');
   }
-  ==== {"messages":["threw"]}
+  ==== {"messages":[],"hasCompileTimeError":1}
   >>>>
   class C {
     m() {
-      try {
-        toplevel();
-      } catch (e) {
-        print('threw');
-      }
+      toplevel();
     }
   }
   var instance;
diff --git a/pkg/front_end/testcases/dartino/static_field_to_instance_field.incremental.yaml b/pkg/front_end/testcases/dartino/static_field_to_instance_field.incremental.yaml
index 5823153..b75163d 100644
--- a/pkg/front_end/testcases/dartino/static_field_to_instance_field.incremental.yaml
+++ b/pkg/front_end/testcases/dartino/static_field_to_instance_field.incremental.yaml
@@ -7,13 +7,13 @@
 
   class C {
   <<<< ["[instance] is null","v1","[instance.x] threw"]
-    static int x;
-  ==== ["[C.x] threw","v2"]
-    int x;
+    static String x;
+  ==== {"messages":[],"hasCompileTimeError":1}
+    String x;
   >>>>
   }
 
-  var instance;
+  dynamic instance;
 
   main() {
     if (instance == null) {
diff --git a/pkg/front_end/testcases/dartino/super_call_signature_change.incremental.yaml b/pkg/front_end/testcases/dartino/super_call_signature_change.incremental.yaml
index 8cee0a9..d750812 100644
--- a/pkg/front_end/testcases/dartino/super_call_signature_change.incremental.yaml
+++ b/pkg/front_end/testcases/dartino/super_call_signature_change.incremental.yaml
@@ -5,11 +5,11 @@
 main.dart.patch: |
   // Test that super calls are dispatched correctly
   class C {
-  <<<< ["instance is null", "v1", "super.foo()", "super.foo(42) threw"]
+  <<<< ["instance is null", "v1", "super.foo()"]
     foo() {
       print('v1');
     }
-  ==== ["super.foo() threw", "v2", "super.foo(42)"]
+  ==== {"messages":[],"hasCompileTimeError":1}
     foo(int i) {
       print('v2');
     }
@@ -17,8 +17,7 @@
   }
 
   class B extends C {
-    superFooNoArgs() => super.foo();
-    superFooOneArg(x) => super.foo(x);
+    superFoo() => super.foo();
   }
 
   var instance;
@@ -28,16 +27,6 @@
       print('instance is null');
       instance = new B();
     }
-    try {
-      instance.superFooNoArgs();
-      print("super.foo()");
-    } catch (e) {
-      print("super.foo() threw");
-    }
-    try {
-      instance.superFooOneArg(42);
-      print("super.foo(42)");
-    } catch (e) {
-      print("super.foo(42) threw");
-    }
+    instance.superFoo();
+    print("super.foo()");
   }
diff --git a/pkg/front_end/testcases/dartino/super_is_parameter.incremental.yaml b/pkg/front_end/testcases/dartino/super_is_parameter.incremental.yaml
index fef1a3e..f770d0a 100644
--- a/pkg/front_end/testcases/dartino/super_is_parameter.incremental.yaml
+++ b/pkg/front_end/testcases/dartino/super_is_parameter.incremental.yaml
@@ -5,7 +5,7 @@
 main.dart.patch: |
   <<<< []
   class A<S> {
-  ==== []
+  ==== {"messages":[],"hasCompileTimeError":1}
   class A<S extends num> {
   >>>>
     S field;
diff --git a/pkg/front_end/testcases/dartino/two_updates_with_removal.incremental.yaml b/pkg/front_end/testcases/dartino/two_updates_with_removal.incremental.yaml
index 8106a59..4300168 100644
--- a/pkg/front_end/testcases/dartino/two_updates_with_removal.incremental.yaml
+++ b/pkg/front_end/testcases/dartino/two_updates_with_removal.incremental.yaml
@@ -14,13 +14,9 @@
   foo() {
     print("Hello, Brave New World!");
   }
-  ==== "threw"
+  ==== {"messages":[],"hasCompileTimeError":1}
   >>>>
 
   main() {
-    try {
-      foo();
-    } catch (e) {
-      print("threw");
-    }
+    foo();
   }
diff --git a/pkg/front_end/testcases/expression/class_type_param_reference_arg_inferred.expression.yaml.expect b/pkg/front_end/testcases/expression/class_type_param_reference_arg_inferred.expression.yaml.expect
index ee48a6d..4842362 100644
--- a/pkg/front_end/testcases/expression/class_type_param_reference_arg_inferred.expression.yaml.expect
+++ b/pkg/front_end/testcases/expression/class_type_param_reference_arg_inferred.expression.yaml.expect
@@ -1,6 +1,6 @@
 Errors: {
 }
 method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr(dynamic x) → dynamic
-  return () → dart.core::Null* {
+  return () → dart.core::Null? {
     x = main::id<dynamic>(x);
   };
diff --git a/pkg/front_end/testcases/expression/class_type_param_reference_ctor_inferred.expression.yaml.expect b/pkg/front_end/testcases/expression/class_type_param_reference_ctor_inferred.expression.yaml.expect
index e41764a..5d5e32a 100644
--- a/pkg/front_end/testcases/expression/class_type_param_reference_ctor_inferred.expression.yaml.expect
+++ b/pkg/front_end/testcases/expression/class_type_param_reference_ctor_inferred.expression.yaml.expect
@@ -1,6 +1,6 @@
 Errors: {
 }
 method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr(dynamic x) → dynamic
-  return () → dart.core::Null* {
+  return () → dart.core::Null? {
     x = new main::A::•<dynamic>();
   };
diff --git a/pkg/front_end/testcases/expression/lib_ctor.expression.yaml.expect b/pkg/front_end/testcases/expression/lib_ctor.expression.yaml.expect
index 9398271..dc61171 100644
--- a/pkg/front_end/testcases/expression/lib_ctor.expression.yaml.expect
+++ b/pkg/front_end/testcases/expression/lib_ctor.expression.yaml.expect
@@ -1,7 +1,7 @@
 Errors: {
 }
 method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
-  return () → dart.core::Null* {
+  return () → dart.core::Null? {
     new main::A::•<dynamic>();
     const main::A::•<dynamic>();
   };
diff --git a/pkg/front_end/testcases/expression/lib_external_ctor.expression.yaml.expect b/pkg/front_end/testcases/expression/lib_external_ctor.expression.yaml.expect
index f2dfa42..4bc18c6 100644
--- a/pkg/front_end/testcases/expression/lib_external_ctor.expression.yaml.expect
+++ b/pkg/front_end/testcases/expression/lib_external_ctor.expression.yaml.expect
@@ -4,7 +4,7 @@
            ^^^^^^^
 }
 method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
-  return () → dart.core::Null* {
+  return () → dart.core::Null? {
     throw new dart.core::AbstractClassInstantiationError::•("Process");
     dart.io::File::fromUri(dart.core::Uri::parse("file://test.dart"));
   };
diff --git a/pkg/front_end/testcases/expression/param_capture.expression.yaml.expect b/pkg/front_end/testcases/expression/param_capture.expression.yaml.expect
index 81af55b..36a812e 100644
--- a/pkg/front_end/testcases/expression/param_capture.expression.yaml.expect
+++ b/pkg/front_end/testcases/expression/param_capture.expression.yaml.expect
@@ -1,6 +1,6 @@
 Errors: {
 }
 method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr(dynamic x, dynamic y) → dynamic
-  return () → dart.core::Null* {
+  return () → dart.core::Null? {
     x = x.+(y);
   };
diff --git a/pkg/front_end/testcases/expression/type_param_shadow_arg_ctor_inferred.expression.yaml.expect b/pkg/front_end/testcases/expression/type_param_shadow_arg_ctor_inferred.expression.yaml.expect
index 82ea2ad..8789584 100644
--- a/pkg/front_end/testcases/expression/type_param_shadow_arg_ctor_inferred.expression.yaml.expect
+++ b/pkg/front_end/testcases/expression/type_param_shadow_arg_ctor_inferred.expression.yaml.expect
@@ -6,6 +6,6 @@
               ^
 }
 method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr<T extends dynamic>() → dynamic
-  return () → dart.core::Null* {
+  return () → dart.core::Null? {
     main::A::debugExpr::T* k = let final<BottomType> #t1 = invalid-expression "org-dartlang-debug:synthetic_debug_expression:2:13: Error: A value of type 'A<dynamic>' can't be assigned to a variable of type 'T'.\n - 'A' is from 'pkg/front_end/testcases/expression/main.dart'.\nTry changing the type of the left hand side, or casting the right hand side to 'T'.\n  T k = new A();\n            ^" in new main::A::•<dynamic>() as{TypeError} <BottomType>;
   };
diff --git a/pkg/front_end/testcases/expression/type_param_shadow_arg_inferred.expression.yaml.expect b/pkg/front_end/testcases/expression/type_param_shadow_arg_inferred.expression.yaml.expect
index 140cb36..a7a450a 100644
--- a/pkg/front_end/testcases/expression/type_param_shadow_arg_inferred.expression.yaml.expect
+++ b/pkg/front_end/testcases/expression/type_param_shadow_arg_inferred.expression.yaml.expect
@@ -1,7 +1,7 @@
 Errors: {
 }
 method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr<T extends dynamic>() → dynamic
-  return () → dart.core::Null* {
+  return () → dart.core::Null? {
     main::A::debugExpr::T* k = null;
     k = main::id<main::A::debugExpr::T*>(k);
   };
diff --git a/pkg/front_end/testcases/expression/type_param_shadow_var.expression.yaml.expect b/pkg/front_end/testcases/expression/type_param_shadow_var.expression.yaml.expect
index ad817cd..50019f0 100644
--- a/pkg/front_end/testcases/expression/type_param_shadow_var.expression.yaml.expect
+++ b/pkg/front_end/testcases/expression/type_param_shadow_var.expression.yaml.expect
@@ -1,6 +1,6 @@
 Errors: {
 }
 method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr<T extends dynamic>(dynamic x) → dynamic
-  return () → dart.core::Null* {
+  return () → dart.core::Null? {
     main::A::debugExpr::T* x = null;
   };
diff --git a/pkg/front_end/testcases/extensions/compounds.dart b/pkg/front_end/testcases/extensions/compounds.dart
new file mode 100644
index 0000000..1664612
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/compounds.dart
@@ -0,0 +1,108 @@
+// 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 Number {
+  final int value;
+
+  Number(this.value);
+
+  int get hashCode => value.hashCode;
+
+  bool operator ==(Object other) => other is Number && value == other.value;
+
+  String toString() => 'Number($value)';
+}
+
+extension NumberExtension on Number {
+  Number operator +(Object other) {
+    if (other is int) {
+      return new Number(value + other);
+    } else if (other is Number) {
+      return new Number(value + other.value);
+    } else {
+      throw new ArgumentError('$other');
+    }
+  }
+  Number operator -(Object other)  {
+    if (other is int) {
+     return new Number(value - other);
+    } else if (other is Number) {
+      return new Number(value - other.value);
+    } else {
+      throw new ArgumentError('$other');
+    }
+  }
+}
+
+class Class {
+  Number field;
+
+  Class(this.field);
+}
+
+extension ClassExtension on Class {
+  Number get property => field;
+  void set property(Number value) {
+    field = value;
+  }
+}
+
+main() {
+  testLocals();
+  testProperties();
+}
+
+testLocals() {
+  Number n0 = new Number(0);
+  Number n1 = new Number(1);
+  Number n2 = new Number(2);
+  Number v = n0;
+  expect(n0, v);
+  expect(n1, v += n1);
+  expect(n2, v += n1);
+  expect(n0, v -= n2);
+  expect(n1, v += n1);
+  expect(n0, v -= n1);
+  expect(n1, ++v);
+  expect(n0, --v);
+  expect(n0, v++);
+  expect(n1, v--);
+  expect(n0, v);
+}
+
+testProperties() {
+  Number n0 = new Number(0);
+  Number n1 = new Number(1);
+  Number n2 = new Number(2);
+  Class v = new Class(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.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(expected, actual) {
+  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
new file mode 100644
index 0000000..10363aa
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/compounds.dart.outline.expect
@@ -0,0 +1,44 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Number extends core::Object {
+  final field core::int* value;
+  constructor •(core::int* value) → self::Number*
+    ;
+  get hashCode() → core::int*
+    ;
+  operator ==(core::Object* other) → core::bool*
+    ;
+  method toString() → core::String*
+    ;
+}
+class Class extends core::Object {
+  field self::Number* field;
+  constructor •(self::Number* field) → self::Class*
+    ;
+}
+extension NumberExtension on self::Number* {
+  operator + = self::NumberExtension|+;
+  operator - = self::NumberExtension|-;
+}
+extension ClassExtension on self::Class* {
+  get property = self::ClassExtension|get#property;
+  set property = self::ClassExtension|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*
+  ;
+static method ClassExtension|get#property(final self::Class* #this) → self::Number*
+  ;
+static method ClassExtension|set#property(final self::Class* #this, self::Number* value) → void
+  ;
+static method main() → dynamic
+  ;
+static method testLocals() → dynamic
+  ;
+static method testProperties() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/extensions/compounds.dart.strong.expect b/pkg/front_end/testcases/extensions/compounds.dart.strong.expect
new file mode 100644
index 0000000..1360e1d
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/compounds.dart.strong.expect
@@ -0,0 +1,115 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Number extends core::Object {
+  final field core::int* value;
+  constructor •(core::int* value) → self::Number*
+    : self::Number::value = value, super core::Object::•()
+    ;
+  get hashCode() → core::int*
+    return this.{self::Number::value}.{core::num::hashCode};
+  operator ==(core::Object* other) → core::bool*
+    return other is self::Number* && this.{self::Number::value}.{core::num::==}(other{self::Number*}.{self::Number::value});
+  method toString() → core::String*
+    return "Number(${this.{self::Number::value}})";
+}
+class Class extends core::Object {
+  field self::Number* field;
+  constructor •(self::Number* field) → self::Class*
+    : self::Class::field = field, super core::Object::•()
+    ;
+}
+extension NumberExtension on self::Number* {
+  operator + = self::NumberExtension|+;
+  operator - = self::NumberExtension|-;
+}
+extension ClassExtension on self::Class* {
+  get property = self::ClassExtension|get#property;
+  set property = self::ClassExtension|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*}));
+  }
+  else
+    if(other is self::Number*) {
+      return new self::Number::•(#this.{self::Number::value}.{core::num::+}(other{self::Number*}.{self::Number::value}));
+    }
+    else {
+      throw new core::ArgumentError::•("${other}");
+    }
+}
+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*}));
+  }
+  else
+    if(other is self::Number*) {
+      return new self::Number::•(#this.{self::Number::value}.{core::num::-}(other{self::Number*}.{self::Number::value}));
+    }
+    else {
+      throw new core::ArgumentError::•("${other}");
+    }
+}
+static method ClassExtension|get#property(final self::Class* #this) → self::Number*
+  return #this.{self::Class::field};
+static method ClassExtension|set#property(final self::Class* #this, self::Number* value) → self::Number* {
+  final self::Number* #t1 = value;
+  #this.{self::Class::field} = value;
+  return #t1;
+}
+static method main() → dynamic {
+  self::testLocals();
+  self::testProperties();
+}
+static method testLocals() → dynamic {
+  self::Number* n0 = new self::Number::•(0);
+  self::Number* n1 = new self::Number::•(1);
+  self::Number* n2 = new self::Number::•(2);
+  self::Number* v = n0;
+  self::expect(n0, v);
+  self::expect(n1, v = self::NumberExtension|+(v, n1));
+  self::expect(n2, v = self::NumberExtension|+(v, n1));
+  self::expect(n0, v = self::NumberExtension|-(v, n2));
+  self::expect(n1, v = self::NumberExtension|+(v, n1));
+  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* #t2 = v in let final self::Number* #t3 = v = self::NumberExtension|+(#t2, 1) in #t2);
+  self::expect(n1, let final self::Number* #t4 = v in let final self::Number* #t5 = v = self::NumberExtension|-(#t4, 1) in #t4);
+  self::expect(n0, v);
+}
+static method testProperties() → 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, v.{self::Class::field});
+  self::expect(n1, let final self::Class* #t6 = v in #t6.{self::Class::field} = self::NumberExtension|+(#t6.{self::Class::field}, n1));
+  self::expect(n2, let final self::Class* #t7 = v in #t7.{self::Class::field} = self::NumberExtension|+(#t7.{self::Class::field}, n1));
+  self::expect(n0, let final self::Class* #t8 = v in #t8.{self::Class::field} = self::NumberExtension|-(#t8.{self::Class::field}, n2));
+  self::expect(n1, let final self::Class* #t9 = v in #t9.{self::Class::field} = self::NumberExtension|+(#t9.{self::Class::field}, n1));
+  self::expect(n0, let final self::Class* #t10 = v in #t10.{self::Class::field} = self::NumberExtension|-(#t10.{self::Class::field}, n1));
+  self::expect(n1, let final self::Class* #t11 = v in #t11.{self::Class::field} = self::NumberExtension|+(#t11.{self::Class::field}, 1));
+  self::expect(n0, let final self::Class* #t12 = v in #t12.{self::Class::field} = self::NumberExtension|-(#t12.{self::Class::field}, 1));
+  self::expect(n0, let final self::Class* #t13 = v in let final self::Number* #t14 = #t13.{self::Class::field} in let final self::Number* #t15 = #t13.{self::Class::field} = self::NumberExtension|+(#t14, 1) in #t14);
+  self::expect(n1, let final self::Class* #t16 = v in let final self::Number* #t17 = #t16.{self::Class::field} in let final self::Number* #t18 = #t16.{self::Class::field} = self::NumberExtension|-(#t17, 1) in #t17);
+  self::expect(n0, v.{self::Class::field});
+  self::expect(n0, self::ClassExtension|get#property(v));
+  self::expect(n1, let final self::Class* #t19 = v in self::ClassExtension|set#property(#t19, self::NumberExtension|+(self::ClassExtension|get#property(#t19), n1)));
+  self::expect(n2, let final self::Class* #t20 = v in self::ClassExtension|set#property(#t20, self::NumberExtension|+(self::ClassExtension|get#property(#t20), n1)));
+  self::expect(n0, let final self::Class* #t21 = v in self::ClassExtension|set#property(#t21, self::NumberExtension|-(self::ClassExtension|get#property(#t21), n2)));
+  self::expect(n1, let final self::Class* #t22 = v in self::ClassExtension|set#property(#t22, self::NumberExtension|+(self::ClassExtension|get#property(#t22), n1)));
+  self::expect(n0, let final self::Class* #t23 = v in self::ClassExtension|set#property(#t23, self::NumberExtension|-(self::ClassExtension|get#property(#t23), n1)));
+  self::expect(n1, let final self::Class* #t24 = v in self::ClassExtension|set#property(#t24, self::NumberExtension|+(self::ClassExtension|get#property(#t24), 1)));
+  self::expect(n0, let final self::Class* #t25 = v in self::ClassExtension|set#property(#t25, self::NumberExtension|-(self::ClassExtension|get#property(#t25), 1)));
+  self::expect(n0, let final self::Class* #t26 = v in let final self::Number* #t27 = self::ClassExtension|get#property(#t26) in let final self::Number* #t28 = self::ClassExtension|set#property(#t26, self::NumberExtension|+(#t27, 1)) in #t27);
+  self::expect(n1, let final self::Class* #t29 = v in let final self::Number* #t30 = self::ClassExtension|get#property(#t29) in let final self::Number* #t31 = self::ClassExtension|set#property(#t29, self::NumberExtension|-(#t30, 1)) in #t30);
+  self::expect(n0, self::ClassExtension|get#property(v));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual)) {
+    throw "Mismatch: expected=${expected}, actual=${actual}";
+  }
+}
diff --git a/pkg/front_end/testcases/extensions/compounds.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/compounds.dart.strong.transformed.expect
new file mode 100644
index 0000000..1360e1d
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/compounds.dart.strong.transformed.expect
@@ -0,0 +1,115 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Number extends core::Object {
+  final field core::int* value;
+  constructor •(core::int* value) → self::Number*
+    : self::Number::value = value, super core::Object::•()
+    ;
+  get hashCode() → core::int*
+    return this.{self::Number::value}.{core::num::hashCode};
+  operator ==(core::Object* other) → core::bool*
+    return other is self::Number* && this.{self::Number::value}.{core::num::==}(other{self::Number*}.{self::Number::value});
+  method toString() → core::String*
+    return "Number(${this.{self::Number::value}})";
+}
+class Class extends core::Object {
+  field self::Number* field;
+  constructor •(self::Number* field) → self::Class*
+    : self::Class::field = field, super core::Object::•()
+    ;
+}
+extension NumberExtension on self::Number* {
+  operator + = self::NumberExtension|+;
+  operator - = self::NumberExtension|-;
+}
+extension ClassExtension on self::Class* {
+  get property = self::ClassExtension|get#property;
+  set property = self::ClassExtension|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*}));
+  }
+  else
+    if(other is self::Number*) {
+      return new self::Number::•(#this.{self::Number::value}.{core::num::+}(other{self::Number*}.{self::Number::value}));
+    }
+    else {
+      throw new core::ArgumentError::•("${other}");
+    }
+}
+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*}));
+  }
+  else
+    if(other is self::Number*) {
+      return new self::Number::•(#this.{self::Number::value}.{core::num::-}(other{self::Number*}.{self::Number::value}));
+    }
+    else {
+      throw new core::ArgumentError::•("${other}");
+    }
+}
+static method ClassExtension|get#property(final self::Class* #this) → self::Number*
+  return #this.{self::Class::field};
+static method ClassExtension|set#property(final self::Class* #this, self::Number* value) → self::Number* {
+  final self::Number* #t1 = value;
+  #this.{self::Class::field} = value;
+  return #t1;
+}
+static method main() → dynamic {
+  self::testLocals();
+  self::testProperties();
+}
+static method testLocals() → dynamic {
+  self::Number* n0 = new self::Number::•(0);
+  self::Number* n1 = new self::Number::•(1);
+  self::Number* n2 = new self::Number::•(2);
+  self::Number* v = n0;
+  self::expect(n0, v);
+  self::expect(n1, v = self::NumberExtension|+(v, n1));
+  self::expect(n2, v = self::NumberExtension|+(v, n1));
+  self::expect(n0, v = self::NumberExtension|-(v, n2));
+  self::expect(n1, v = self::NumberExtension|+(v, n1));
+  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* #t2 = v in let final self::Number* #t3 = v = self::NumberExtension|+(#t2, 1) in #t2);
+  self::expect(n1, let final self::Number* #t4 = v in let final self::Number* #t5 = v = self::NumberExtension|-(#t4, 1) in #t4);
+  self::expect(n0, v);
+}
+static method testProperties() → 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, v.{self::Class::field});
+  self::expect(n1, let final self::Class* #t6 = v in #t6.{self::Class::field} = self::NumberExtension|+(#t6.{self::Class::field}, n1));
+  self::expect(n2, let final self::Class* #t7 = v in #t7.{self::Class::field} = self::NumberExtension|+(#t7.{self::Class::field}, n1));
+  self::expect(n0, let final self::Class* #t8 = v in #t8.{self::Class::field} = self::NumberExtension|-(#t8.{self::Class::field}, n2));
+  self::expect(n1, let final self::Class* #t9 = v in #t9.{self::Class::field} = self::NumberExtension|+(#t9.{self::Class::field}, n1));
+  self::expect(n0, let final self::Class* #t10 = v in #t10.{self::Class::field} = self::NumberExtension|-(#t10.{self::Class::field}, n1));
+  self::expect(n1, let final self::Class* #t11 = v in #t11.{self::Class::field} = self::NumberExtension|+(#t11.{self::Class::field}, 1));
+  self::expect(n0, let final self::Class* #t12 = v in #t12.{self::Class::field} = self::NumberExtension|-(#t12.{self::Class::field}, 1));
+  self::expect(n0, let final self::Class* #t13 = v in let final self::Number* #t14 = #t13.{self::Class::field} in let final self::Number* #t15 = #t13.{self::Class::field} = self::NumberExtension|+(#t14, 1) in #t14);
+  self::expect(n1, let final self::Class* #t16 = v in let final self::Number* #t17 = #t16.{self::Class::field} in let final self::Number* #t18 = #t16.{self::Class::field} = self::NumberExtension|-(#t17, 1) in #t17);
+  self::expect(n0, v.{self::Class::field});
+  self::expect(n0, self::ClassExtension|get#property(v));
+  self::expect(n1, let final self::Class* #t19 = v in self::ClassExtension|set#property(#t19, self::NumberExtension|+(self::ClassExtension|get#property(#t19), n1)));
+  self::expect(n2, let final self::Class* #t20 = v in self::ClassExtension|set#property(#t20, self::NumberExtension|+(self::ClassExtension|get#property(#t20), n1)));
+  self::expect(n0, let final self::Class* #t21 = v in self::ClassExtension|set#property(#t21, self::NumberExtension|-(self::ClassExtension|get#property(#t21), n2)));
+  self::expect(n1, let final self::Class* #t22 = v in self::ClassExtension|set#property(#t22, self::NumberExtension|+(self::ClassExtension|get#property(#t22), n1)));
+  self::expect(n0, let final self::Class* #t23 = v in self::ClassExtension|set#property(#t23, self::NumberExtension|-(self::ClassExtension|get#property(#t23), n1)));
+  self::expect(n1, let final self::Class* #t24 = v in self::ClassExtension|set#property(#t24, self::NumberExtension|+(self::ClassExtension|get#property(#t24), 1)));
+  self::expect(n0, let final self::Class* #t25 = v in self::ClassExtension|set#property(#t25, self::NumberExtension|-(self::ClassExtension|get#property(#t25), 1)));
+  self::expect(n0, let final self::Class* #t26 = v in let final self::Number* #t27 = self::ClassExtension|get#property(#t26) in let final self::Number* #t28 = self::ClassExtension|set#property(#t26, self::NumberExtension|+(#t27, 1)) in #t27);
+  self::expect(n1, let final self::Class* #t29 = v in let final self::Number* #t30 = self::ClassExtension|get#property(#t29) in let final self::Number* #t31 = self::ClassExtension|set#property(#t29, self::NumberExtension|-(#t30, 1)) in #t30);
+  self::expect(n0, self::ClassExtension|get#property(v));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual)) {
+    throw "Mismatch: expected=${expected}, actual=${actual}";
+  }
+}
diff --git a/pkg/front_end/testcases/extensions/compounds.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/compounds.dart.type_promotion.expect
new file mode 100644
index 0000000..28a5f00
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/compounds.dart.type_promotion.expect
@@ -0,0 +1,42 @@
+pkg/front_end/testcases/extensions/compounds.dart:12:43: Context: Possible promotion of other@340
+  bool operator ==(Object other) => other is Number && value == other.value;
+                                          ^^
+pkg/front_end/testcases/extensions/compounds.dart:19:15: Context: Possible promotion of other@501
+    if (other is int) {
+              ^^
+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
+    if (other is int) {
+              ^^
+pkg/front_end/testcases/extensions/compounds.dart:30:22: Context: Possible promotion of other@501
+    } else if (other is Number) {
+                     ^^
+pkg/front_end/testcases/extensions/compounds.dart:62:16: Context: Write to v@1309
+  expect(n1, v += n1);
+               ^^
+pkg/front_end/testcases/extensions/compounds.dart:63:16: Context: Write to v@1309
+  expect(n2, v += n1);
+               ^^
+pkg/front_end/testcases/extensions/compounds.dart:64:16: Context: Write to v@1309
+  expect(n0, v -= n2);
+               ^^
+pkg/front_end/testcases/extensions/compounds.dart:65:16: Context: Write to v@1309
+  expect(n1, v += n1);
+               ^^
+pkg/front_end/testcases/extensions/compounds.dart:66:16: Context: Write to v@1309
+  expect(n0, v -= n1);
+               ^^
+pkg/front_end/testcases/extensions/compounds.dart:67:14: Context: Write to v@1309
+  expect(n1, ++v);
+             ^^
+pkg/front_end/testcases/extensions/compounds.dart:68:14: Context: Write to v@1309
+  expect(n0, --v);
+             ^^
+pkg/front_end/testcases/extensions/compounds.dart:69:15: Context: Write to v@1309
+  expect(n0, v++);
+              ^^
+pkg/front_end/testcases/extensions/compounds.dart:70:15: Context: Write to v@1309
+  expect(n1, v--);
+              ^^
diff --git a/pkg/front_end/testcases/extensions/direct_static_access.dart.strong.expect b/pkg/front_end/testcases/extensions/direct_static_access.dart.strong.expect
index a7051b9..19243a9 100644
--- a/pkg/front_end/testcases/extensions/direct_static_access.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/direct_static_access.dart.strong.expect
@@ -109,15 +109,15 @@
   ({value: dynamic}) →* dynamic tearOffNamed = #C5;
   tearOffNamed.call();
   tearOffNamed.call(value: value);
-  <S extends core::Object* = dynamic>(self::Extension|genericWriteSetterRequired::S*) →* dynamic tearOffGenericRequired = #C6;
+  <S extends core::Object* = dynamic>(S*) →* dynamic tearOffGenericRequired = #C6;
   tearOffGenericRequired.call<core::int*>(value);
   tearOffGenericRequired.call<core::int*>(value);
-  <S extends core::Object* = dynamic>([self::Extension|genericWriteSetterOptional::S*]) →* dynamic tearOffGenericOptional = #C7;
+  <S extends core::Object* = dynamic>([S*]) →* dynamic tearOffGenericOptional = #C7;
   tearOffGenericOptional.call<dynamic>();
   tearOffGenericOptional.call<core::int*>();
   tearOffGenericOptional.call<core::int*>(value);
   tearOffGenericOptional.call<core::int*>(value);
-  <S extends core::Object* = dynamic>({value: self::Extension|genericWriteSetterNamed::S*}) →* dynamic tearOffGenericNamed = #C8;
+  <S extends core::Object* = dynamic>({value: S*}) →* dynamic tearOffGenericNamed = #C8;
   tearOffGenericNamed.call<dynamic>();
   tearOffGenericNamed.call<core::int*>();
   tearOffGenericNamed.call<core::int*>(value: value);
@@ -176,15 +176,15 @@
   ({value: dynamic}) →* dynamic tearOffNamed = #C5;
   tearOffNamed.call();
   tearOffNamed.call(value: value);
-  <S extends core::Object* = dynamic>(self::Extension|genericWriteSetterRequired::S*) →* dynamic tearOffGenericRequired = #C6;
+  <S extends core::Object* = dynamic>(S*) →* dynamic tearOffGenericRequired = #C6;
   tearOffGenericRequired.call<self::Extension|tearOffsFromInstanceContext::T*>(value);
   tearOffGenericRequired.call<self::Extension|tearOffsFromInstanceContext::T*>(value);
-  <S extends core::Object* = dynamic>([self::Extension|genericWriteSetterOptional::S*]) →* dynamic tearOffGenericOptional = #C7;
+  <S extends core::Object* = dynamic>([S*]) →* dynamic tearOffGenericOptional = #C7;
   tearOffGenericOptional.call<dynamic>();
   tearOffGenericOptional.call<self::Extension|tearOffsFromInstanceContext::T*>();
   tearOffGenericOptional.call<self::Extension|tearOffsFromInstanceContext::T*>(value);
   tearOffGenericOptional.call<self::Extension|tearOffsFromInstanceContext::T*>(value);
-  <S extends core::Object* = dynamic>({value: self::Extension|genericWriteSetterNamed::S*}) →* dynamic tearOffGenericNamed = #C8;
+  <S extends core::Object* = dynamic>({value: S*}) →* dynamic tearOffGenericNamed = #C8;
   tearOffGenericNamed.call<dynamic>();
   tearOffGenericNamed.call<self::Extension|tearOffsFromInstanceContext::T*>();
   tearOffGenericNamed.call<self::Extension|tearOffsFromInstanceContext::T*>(value: value);
diff --git a/pkg/front_end/testcases/extensions/direct_static_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/direct_static_access.dart.strong.transformed.expect
index a7051b9..19243a9 100644
--- a/pkg/front_end/testcases/extensions/direct_static_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/direct_static_access.dart.strong.transformed.expect
@@ -109,15 +109,15 @@
   ({value: dynamic}) →* dynamic tearOffNamed = #C5;
   tearOffNamed.call();
   tearOffNamed.call(value: value);
-  <S extends core::Object* = dynamic>(self::Extension|genericWriteSetterRequired::S*) →* dynamic tearOffGenericRequired = #C6;
+  <S extends core::Object* = dynamic>(S*) →* dynamic tearOffGenericRequired = #C6;
   tearOffGenericRequired.call<core::int*>(value);
   tearOffGenericRequired.call<core::int*>(value);
-  <S extends core::Object* = dynamic>([self::Extension|genericWriteSetterOptional::S*]) →* dynamic tearOffGenericOptional = #C7;
+  <S extends core::Object* = dynamic>([S*]) →* dynamic tearOffGenericOptional = #C7;
   tearOffGenericOptional.call<dynamic>();
   tearOffGenericOptional.call<core::int*>();
   tearOffGenericOptional.call<core::int*>(value);
   tearOffGenericOptional.call<core::int*>(value);
-  <S extends core::Object* = dynamic>({value: self::Extension|genericWriteSetterNamed::S*}) →* dynamic tearOffGenericNamed = #C8;
+  <S extends core::Object* = dynamic>({value: S*}) →* dynamic tearOffGenericNamed = #C8;
   tearOffGenericNamed.call<dynamic>();
   tearOffGenericNamed.call<core::int*>();
   tearOffGenericNamed.call<core::int*>(value: value);
@@ -176,15 +176,15 @@
   ({value: dynamic}) →* dynamic tearOffNamed = #C5;
   tearOffNamed.call();
   tearOffNamed.call(value: value);
-  <S extends core::Object* = dynamic>(self::Extension|genericWriteSetterRequired::S*) →* dynamic tearOffGenericRequired = #C6;
+  <S extends core::Object* = dynamic>(S*) →* dynamic tearOffGenericRequired = #C6;
   tearOffGenericRequired.call<self::Extension|tearOffsFromInstanceContext::T*>(value);
   tearOffGenericRequired.call<self::Extension|tearOffsFromInstanceContext::T*>(value);
-  <S extends core::Object* = dynamic>([self::Extension|genericWriteSetterOptional::S*]) →* dynamic tearOffGenericOptional = #C7;
+  <S extends core::Object* = dynamic>([S*]) →* dynamic tearOffGenericOptional = #C7;
   tearOffGenericOptional.call<dynamic>();
   tearOffGenericOptional.call<self::Extension|tearOffsFromInstanceContext::T*>();
   tearOffGenericOptional.call<self::Extension|tearOffsFromInstanceContext::T*>(value);
   tearOffGenericOptional.call<self::Extension|tearOffsFromInstanceContext::T*>(value);
-  <S extends core::Object* = dynamic>({value: self::Extension|genericWriteSetterNamed::S*}) →* dynamic tearOffGenericNamed = #C8;
+  <S extends core::Object* = dynamic>({value: S*}) →* dynamic tearOffGenericNamed = #C8;
   tearOffGenericNamed.call<dynamic>();
   tearOffGenericNamed.call<self::Extension|tearOffsFromInstanceContext::T*>();
   tearOffGenericNamed.call<self::Extension|tearOffsFromInstanceContext::T*>(value: value);
diff --git a/pkg/front_end/testcases/extensions/index.dart b/pkg/front_end/testcases/extensions/index.dart
index f34eac8..582d067 100644
--- a/pkg/front_end/testcases/extensions/index.dart
+++ b/pkg/front_end/testcases/extensions/index.dart
@@ -20,8 +20,28 @@
   map1.put(0, '0');
   expect('0', map1[0]);
   expect(null, map1[1]);
-  expect('1', map1[1] = '1');
+  map1[1] = '1';
   expect('1', map1[1]);
+  expect('2', map1[1] = '2');
+  expect('2', map1[1]);
+  map1[1] ??= '3';
+  expect('2', map1[1]);
+  expect('2', map1[1] ??= '4');
+  expect('2', map1[1]);
+  map1[2] ??= '2';
+  expect('2', map1[2]);
+  expect('3', map1[3] ??= '3');
+  expect('3', map1[3]);
+
+  MapLike<int, int> map2 = new MapLike();
+  expect(1, map2[0] = 1);
+  expect(3, map2[0] += 2);
+  expect(5, map2[0] += 2);
+  expect(5, map2[0]++);
+  expect(6, map2[0]);
+  expect(5, --map2[0]);
+  expect(5, map2[0]);
+
 }
 
 expect(expected, actual) {
diff --git a/pkg/front_end/testcases/extensions/index.dart.strong.expect b/pkg/front_end/testcases/extensions/index.dart.strong.expect
index 70bdb38..4f14d3dc 100644
--- a/pkg/front_end/testcases/extensions/index.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/index.dart.strong.expect
@@ -26,8 +26,26 @@
   map1.{self::MapLike::put}(0, "0");
   self::expect("0", self::Extension|[]<core::int*, core::String*>(map1, 0));
   self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 1));
-  self::expect("1", let final self::MapLike<core::int*, core::String*>* #t5 = map1 in let final core::int* #t6 = 1 in let final core::String* #t7 = "1" in let final void #t8 = self::Extension|[]=<core::int*, core::String*>(#t5, #t6, #t7) in #t7);
+  self::Extension|[]=<core::int*, core::String*>(map1, 1, "1");
   self::expect("1", self::Extension|[]<core::int*, core::String*>(map1, 1));
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t5 = map1 in let final core::int* #t6 = 1 in let final core::String* #t7 = "2" in let final void #t8 = self::Extension|[]=<core::int*, core::String*>(#t5, #t6, #t7) in #t7);
+  self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
+  let final self::MapLike<core::int*, core::String*>* #t9 = map1 in let final core::int* #t10 = 1 in self::Extension|[]<core::int*, core::String*>(#t9, #t10).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t9, #t10, "3") : null;
+  self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t11 = map1 in let final core::int* #t12 = 1 in let final core::String* #t13 = self::Extension|[]<core::int*, core::String*>(#t11, #t12) in #t13.{core::String::==}(null) ?{core::String*} let final core::String* #t14 = "4" in let final void #t15 = self::Extension|[]=<core::int*, core::String*>(#t11, #t12, #t14) in #t14 : #t13);
+  self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
+  let final self::MapLike<core::int*, core::String*>* #t16 = map1 in let final core::int* #t17 = 2 in self::Extension|[]<core::int*, core::String*>(#t16, #t17).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t16, #t17, "2") : null;
+  self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 2));
+  self::expect("3", let final self::MapLike<core::int*, core::String*>* #t18 = map1 in let final core::int* #t19 = 3 in let final core::String* #t20 = self::Extension|[]<core::int*, core::String*>(#t18, #t19) in #t20.{core::String::==}(null) ?{core::String*} let final core::String* #t21 = "3" in let final void #t22 = self::Extension|[]=<core::int*, core::String*>(#t18, #t19, #t21) in #t21 : #t20);
+  self::expect("3", self::Extension|[]<core::int*, core::String*>(map1, 3));
+  self::MapLike<core::int*, core::int*>* map2 = new self::MapLike::•<core::int*, core::int*>();
+  self::expect(1, let final self::MapLike<core::int*, core::int*>* #t23 = map2 in let final core::int* #t24 = 0 in let final core::int* #t25 = 1 in let final void #t26 = self::Extension|[]=<core::int*, core::int*>(#t23, #t24, #t25) in #t25);
+  self::expect(3, let final self::MapLike<core::int*, core::int*>* #t27 = map2 in let final core::int* #t28 = 0 in let final core::int* #t29 = self::Extension|[]<core::int*, core::int*>(#t27, #t28).{core::num::+}(2) in let final void #t30 = self::Extension|[]=<core::int*, core::int*>(#t27, #t28, #t29) in #t29);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t31 = map2 in let final core::int* #t32 = 0 in let final core::int* #t33 = self::Extension|[]<core::int*, core::int*>(#t31, #t32).{core::num::+}(2) in let final void #t34 = self::Extension|[]=<core::int*, core::int*>(#t31, #t32, #t33) in #t33);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t35 = map2 in let final core::int* #t36 = 0 in let final core::int* #t37 = self::Extension|[]<core::int*, core::int*>(#t35, #t36) in let final void #t38 = self::Extension|[]=<core::int*, core::int*>(#t35, #t36, #t37.{core::num::+}(1)) in #t37);
+  self::expect(6, self::Extension|[]<core::int*, core::int*>(map2, 0));
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t39 = map2 in let final core::int* #t40 = 0 in let final core::int* #t41 = self::Extension|[]<core::int*, core::int*>(#t39, #t40).{core::num::-}(1) in let final void #t42 = self::Extension|[]=<core::int*, core::int*>(#t39, #t40, #t41) in #t41);
+  self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual)) {
diff --git a/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect
index 70bdb38..4f14d3dc 100644
--- a/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect
@@ -26,8 +26,26 @@
   map1.{self::MapLike::put}(0, "0");
   self::expect("0", self::Extension|[]<core::int*, core::String*>(map1, 0));
   self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 1));
-  self::expect("1", let final self::MapLike<core::int*, core::String*>* #t5 = map1 in let final core::int* #t6 = 1 in let final core::String* #t7 = "1" in let final void #t8 = self::Extension|[]=<core::int*, core::String*>(#t5, #t6, #t7) in #t7);
+  self::Extension|[]=<core::int*, core::String*>(map1, 1, "1");
   self::expect("1", self::Extension|[]<core::int*, core::String*>(map1, 1));
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t5 = map1 in let final core::int* #t6 = 1 in let final core::String* #t7 = "2" in let final void #t8 = self::Extension|[]=<core::int*, core::String*>(#t5, #t6, #t7) in #t7);
+  self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
+  let final self::MapLike<core::int*, core::String*>* #t9 = map1 in let final core::int* #t10 = 1 in self::Extension|[]<core::int*, core::String*>(#t9, #t10).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t9, #t10, "3") : null;
+  self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t11 = map1 in let final core::int* #t12 = 1 in let final core::String* #t13 = self::Extension|[]<core::int*, core::String*>(#t11, #t12) in #t13.{core::String::==}(null) ?{core::String*} let final core::String* #t14 = "4" in let final void #t15 = self::Extension|[]=<core::int*, core::String*>(#t11, #t12, #t14) in #t14 : #t13);
+  self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
+  let final self::MapLike<core::int*, core::String*>* #t16 = map1 in let final core::int* #t17 = 2 in self::Extension|[]<core::int*, core::String*>(#t16, #t17).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t16, #t17, "2") : null;
+  self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 2));
+  self::expect("3", let final self::MapLike<core::int*, core::String*>* #t18 = map1 in let final core::int* #t19 = 3 in let final core::String* #t20 = self::Extension|[]<core::int*, core::String*>(#t18, #t19) in #t20.{core::String::==}(null) ?{core::String*} let final core::String* #t21 = "3" in let final void #t22 = self::Extension|[]=<core::int*, core::String*>(#t18, #t19, #t21) in #t21 : #t20);
+  self::expect("3", self::Extension|[]<core::int*, core::String*>(map1, 3));
+  self::MapLike<core::int*, core::int*>* map2 = new self::MapLike::•<core::int*, core::int*>();
+  self::expect(1, let final self::MapLike<core::int*, core::int*>* #t23 = map2 in let final core::int* #t24 = 0 in let final core::int* #t25 = 1 in let final void #t26 = self::Extension|[]=<core::int*, core::int*>(#t23, #t24, #t25) in #t25);
+  self::expect(3, let final self::MapLike<core::int*, core::int*>* #t27 = map2 in let final core::int* #t28 = 0 in let final core::int* #t29 = self::Extension|[]<core::int*, core::int*>(#t27, #t28).{core::num::+}(2) in let final void #t30 = self::Extension|[]=<core::int*, core::int*>(#t27, #t28, #t29) in #t29);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t31 = map2 in let final core::int* #t32 = 0 in let final core::int* #t33 = self::Extension|[]<core::int*, core::int*>(#t31, #t32).{core::num::+}(2) in let final void #t34 = self::Extension|[]=<core::int*, core::int*>(#t31, #t32, #t33) in #t33);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t35 = map2 in let final core::int* #t36 = 0 in let final core::int* #t37 = self::Extension|[]<core::int*, core::int*>(#t35, #t36) in let final void #t38 = self::Extension|[]=<core::int*, core::int*>(#t35, #t36, #t37.{core::num::+}(1)) in #t37);
+  self::expect(6, self::Extension|[]<core::int*, core::int*>(map2, 0));
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t39 = map2 in let final core::int* #t40 = 0 in let final core::int* #t41 = self::Extension|[]<core::int*, core::int*>(#t39, #t40).{core::num::-}(1) in let final void #t42 = self::Extension|[]=<core::int*, core::int*>(#t39, #t40, #t41) in #t41);
+  self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual)) {
diff --git a/pkg/front_end/testcases/extensions/instance_access.dart b/pkg/front_end/testcases/extensions/instance_access.dart
index 249f712..93f74ed 100644
--- a/pkg/front_end/testcases/extensions/instance_access.dart
+++ b/pkg/front_end/testcases/extensions/instance_access.dart
@@ -69,11 +69,13 @@
   Class1 c1 = new Class1(1);
   expect(0, c0.method());
   expect(1, c1.method());
+  expect(1, c1?.method());
   expect(42, c0.genericMethod(42));
   expect(43, c0.genericMethod<num>(43));
   expect(88, c1.genericMethod(87));
   expect(89, c1.genericMethod<num>(88));
   expect(0, c0.property);
+  expect(0, c0?.property);
   expect(42, c0.property = 42);
   expect(1, c1.property);
   expect(87, c0.property = 87);
@@ -87,12 +89,14 @@
   Class2 c0 = new Class2(0);
   Class2 c1 = new Class2(1);
   expect(3, c0.method());
+  expect(3, c0?.method());
   expect(4, c1.method());
   expect(46, c0.genericMethod(42));
   expect(47, c0.genericMethod<num>(43));
   expect(92, c1.genericMethod(87));
   expect(93, c1.genericMethod<num>(88));
   expect(5, c0.property);
+  expect(5, c0?.property);
   expect(42, c0.property = 42);
   expect(48, c0.property);
   expect(6, c1.property);
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 1417dd4..9812038 100644
--- a/pkg/front_end/testcases/extensions/instance_access.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/instance_access.dart.strong.expect
@@ -89,11 +89,13 @@
   self::Class1* c1 = new self::Class1::•(1);
   self::expect(0, self::Extension1|method(c0));
   self::expect(1, self::Extension1|method(c1));
+  self::expect(1, let final self::Class1* #t3 = c1 in #t3.{core::Object::==}(null) ?{core::int*} null : self::Extension1|method(#t3));
   self::expect(42, self::Extension1|genericMethod<core::int*>(c0, 42));
   self::expect(43, self::Extension1|genericMethod<core::num*>(c0, 43));
   self::expect(88, self::Extension1|genericMethod<core::int*>(c1, 87));
   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* #t4 = c0 in #t4.{core::Object::==}(null) ?{core::int*} null : self::Extension1|get#property(#t4));
   self::expect(42, self::Extension1|set#property(c0, 42));
   self::expect(1, self::Extension1|get#property(c1));
   self::expect(87, self::Extension1|set#property(c0, 87));
@@ -106,12 +108,14 @@
   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* #t5 = c0 in #t5.{core::Object::==}(null) ?{core::int*} null : self::Extension2|method(#t5));
   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* #t6 = c0 in #t6.{core::Object::==}(null) ?{core::int*} null : self::Extension2|get#property(#t6));
   self::expect(42, self::Extension2|set#property(c0, 42));
   self::expect(48, self::Extension2|get#property(c0));
   self::expect(6, self::Extension2|get#property(c1));
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 1417dd4..9812038 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
@@ -89,11 +89,13 @@
   self::Class1* c1 = new self::Class1::•(1);
   self::expect(0, self::Extension1|method(c0));
   self::expect(1, self::Extension1|method(c1));
+  self::expect(1, let final self::Class1* #t3 = c1 in #t3.{core::Object::==}(null) ?{core::int*} null : self::Extension1|method(#t3));
   self::expect(42, self::Extension1|genericMethod<core::int*>(c0, 42));
   self::expect(43, self::Extension1|genericMethod<core::num*>(c0, 43));
   self::expect(88, self::Extension1|genericMethod<core::int*>(c1, 87));
   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* #t4 = c0 in #t4.{core::Object::==}(null) ?{core::int*} null : self::Extension1|get#property(#t4));
   self::expect(42, self::Extension1|set#property(c0, 42));
   self::expect(1, self::Extension1|get#property(c1));
   self::expect(87, self::Extension1|set#property(c0, 87));
@@ -106,12 +108,14 @@
   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* #t5 = c0 in #t5.{core::Object::==}(null) ?{core::int*} null : self::Extension2|method(#t5));
   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* #t6 = c0 in #t6.{core::Object::==}(null) ?{core::int*} null : self::Extension2|get#property(#t6));
   self::expect(42, self::Extension2|set#property(c0, 42));
   self::expect(48, self::Extension2|get#property(c0));
   self::expect(6, self::Extension2|get#property(c1));
diff --git a/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.expect b/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.expect
index be0799d..4ba1b5e 100644
--- a/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.expect
@@ -69,10 +69,10 @@
   self::expect(1, tearOff1.call());
   c1 = new self::Class1::•(7.{core::int::unary-}());
   self::expect(1, tearOff1.call());
-  <T extends core::num* = dynamic>(self::Extension1|genericMethod::T*) →* core::int* genericTearOff0 = self::Extension1|get#genericMethod(c0);
+  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff0 = self::Extension1|get#genericMethod(c0);
   self::expect(38, genericTearOff0.call<core::int*>(42));
   self::expect(38, genericTearOff0.call<core::num*>(42));
-  <T extends core::num* = dynamic>(self::Extension1|genericMethod::T*) →* core::int* genericTearOff1 = self::Extension1|get#genericMethod(c1);
+  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff1 = self::Extension1|get#genericMethod(c1);
   self::expect(35, genericTearOff1.call<core::int*>(42));
   self::expect(35, genericTearOff1.call<core::num*>(42));
 }
@@ -87,10 +87,10 @@
   self::expect(3, tearOff1.call());
   c1 = new self::Class2::•(7.{core::int::unary-}());
   self::expect(3, tearOff1.call());
-  <T extends core::num* = dynamic>(self::Extension2|genericMethod::T*) →* core::int* genericTearOff0 = self::Extension2|get#genericMethod(c0);
+  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff0 = self::Extension2|get#genericMethod(c0);
   self::expect(41, genericTearOff0.call<core::int*>(42));
   self::expect(41, genericTearOff0.call<core::num*>(42));
-  <T extends core::num* = dynamic>(self::Extension2|genericMethod::T*) →* core::int* genericTearOff1 = self::Extension2|get#genericMethod(c1);
+  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff1 = self::Extension2|get#genericMethod(c1);
   self::expect(38, genericTearOff1.call<core::int*>(42));
   self::expect(38, genericTearOff1.call<core::num*>(42));
 }
diff --git a/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.transformed.expect
index be0799d..4ba1b5e 100644
--- a/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.transformed.expect
@@ -69,10 +69,10 @@
   self::expect(1, tearOff1.call());
   c1 = new self::Class1::•(7.{core::int::unary-}());
   self::expect(1, tearOff1.call());
-  <T extends core::num* = dynamic>(self::Extension1|genericMethod::T*) →* core::int* genericTearOff0 = self::Extension1|get#genericMethod(c0);
+  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff0 = self::Extension1|get#genericMethod(c0);
   self::expect(38, genericTearOff0.call<core::int*>(42));
   self::expect(38, genericTearOff0.call<core::num*>(42));
-  <T extends core::num* = dynamic>(self::Extension1|genericMethod::T*) →* core::int* genericTearOff1 = self::Extension1|get#genericMethod(c1);
+  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff1 = self::Extension1|get#genericMethod(c1);
   self::expect(35, genericTearOff1.call<core::int*>(42));
   self::expect(35, genericTearOff1.call<core::num*>(42));
 }
@@ -87,10 +87,10 @@
   self::expect(3, tearOff1.call());
   c1 = new self::Class2::•(7.{core::int::unary-}());
   self::expect(3, tearOff1.call());
-  <T extends core::num* = dynamic>(self::Extension2|genericMethod::T*) →* core::int* genericTearOff0 = self::Extension2|get#genericMethod(c0);
+  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff0 = self::Extension2|get#genericMethod(c0);
   self::expect(41, genericTearOff0.call<core::int*>(42));
   self::expect(41, genericTearOff0.call<core::num*>(42));
-  <T extends core::num* = dynamic>(self::Extension2|genericMethod::T*) →* core::int* genericTearOff1 = self::Extension2|get#genericMethod(c1);
+  <T extends core::num* = dynamic>(T*) →* core::int* genericTearOff1 = self::Extension2|get#genericMethod(c1);
   self::expect(38, genericTearOff1.call<core::int*>(42));
   self::expect(38, genericTearOff1.call<core::num*>(42));
 }
diff --git a/pkg/front_end/testcases/extensions/null_aware.dart b/pkg/front_end/testcases/extensions/null_aware.dart
new file mode 100644
index 0000000..d645b13
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/null_aware.dart
@@ -0,0 +1,39 @@
+// 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 {
+  int field;
+}
+
+extension Extension on Class {
+  int get property => field;
+  void set property(int value) {
+    field = value;
+  }
+  int method() => field;
+}
+
+main() {
+  Class c;
+  expect(null, c?.property);
+  expect(null, c?.method);
+  expect(null, c?.method());
+  expect(null, c?.property = 42);
+  c = new Class();
+  expect(null, c?.property);
+  expect(null, c?.method());
+  var tearOff = c?.method;
+  expect(null, tearOff());
+  expect(42, c?.property = 42);
+  expect(42, tearOff());
+  expect(null, c?.property = null);
+  expect(42, c.property ??= 42);
+  expect(42, c.property ??= 87);
+}
+
+expect(expected, actual) {
+  if (expected != actual) {
+    throw 'Mismatch: expected=$expected, actual=$actual';
+  }
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/extensions/null_aware.dart.outline.expect b/pkg/front_end/testcases/extensions/null_aware.dart.outline.expect
new file mode 100644
index 0000000..50dde61
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/null_aware.dart.outline.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  field core::int* field;
+  synthetic constructor •() → self::Class*
+    ;
+}
+extension Extension on self::Class* {
+  get property = self::Extension|get#property;
+  method method = self::Extension|method;
+  tearoff method = self::Extension|get#method;
+  set property = self::Extension|set#property;
+}
+static method Extension|get#property(final self::Class* #this) → core::int*
+  ;
+static method Extension|set#property(final self::Class* #this, core::int* value) → void
+  ;
+static method Extension|method(final self::Class* #this) → core::int*
+  ;
+static method Extension|get#method(final self::Class* #this) → () →* core::int*
+  return () → core::int* => self::Extension|method(#this);
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → 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
new file mode 100644
index 0000000..6b4ef8f
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/null_aware.dart.strong.expect
@@ -0,0 +1,49 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  field core::int* field = null;
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+}
+extension Extension on self::Class* {
+  get property = self::Extension|get#property;
+  method method = self::Extension|method;
+  tearoff method = self::Extension|get#method;
+  set property = self::Extension|set#property;
+}
+static method Extension|get#property(final self::Class* #this) → core::int*
+  return #this.{self::Class::field};
+static method Extension|set#property(final self::Class* #this, core::int* value) → core::int* {
+  final core::int* #t1 = value;
+  #this.{self::Class::field} = value;
+  return #t1;
+}
+static method Extension|method(final self::Class* #this) → core::int*
+  return #this.{self::Class::field};
+static method Extension|get#method(final self::Class* #this) → () →* core::int*
+  return () → core::int* => self::Extension|method(#this);
+static method main() → dynamic {
+  self::Class* c;
+  self::expect(null, let final self::Class* #t2 = c in #t2.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t2));
+  self::expect(null, let final self::Class* #t3 = c in #t3.{core::Object::==}(null) ?{() →* core::int*} null : self::Extension|get#method(#t3));
+  self::expect(null, let final self::Class* #t4 = c in #t4.{core::Object::==}(null) ?{core::int*} null : self::Extension|method(#t4));
+  self::expect(null, let final self::Class* #t5 = c in #t5.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#property(#t5, 42));
+  c = new self::Class::•();
+  self::expect(null, let final self::Class* #t6 = c in #t6.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t6));
+  self::expect(null, let final self::Class* #t7 = c in #t7.{core::Object::==}(null) ?{core::int*} null : self::Extension|method(#t7));
+  () →* core::int* tearOff = let final self::Class* #t8 = c in #t8.{core::Object::==}(null) ?{() →* core::int*} null : self::Extension|get#method(#t8);
+  self::expect(null, tearOff.call());
+  self::expect(42, let final self::Class* #t9 = c in #t9.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#property(#t9, 42));
+  self::expect(42, tearOff.call());
+  self::expect(null, let final self::Class* #t10 = c in #t10.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t10, null));
+  self::expect(42, let final self::Class* #t11 = c in let final core::int* #t12 = self::Extension|get#property(#t11) in #t12.{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t11, 42) : #t12);
+  self::expect(42, let final self::Class* #t13 = c in let final core::int* #t14 = self::Extension|get#property(#t13) in #t14.{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t13, 87) : #t14);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual)) {
+    throw "Mismatch: expected=${expected}, actual=${actual}";
+  }
+}
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
new file mode 100644
index 0000000..6b4ef8f
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/null_aware.dart.strong.transformed.expect
@@ -0,0 +1,49 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  field core::int* field = null;
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+}
+extension Extension on self::Class* {
+  get property = self::Extension|get#property;
+  method method = self::Extension|method;
+  tearoff method = self::Extension|get#method;
+  set property = self::Extension|set#property;
+}
+static method Extension|get#property(final self::Class* #this) → core::int*
+  return #this.{self::Class::field};
+static method Extension|set#property(final self::Class* #this, core::int* value) → core::int* {
+  final core::int* #t1 = value;
+  #this.{self::Class::field} = value;
+  return #t1;
+}
+static method Extension|method(final self::Class* #this) → core::int*
+  return #this.{self::Class::field};
+static method Extension|get#method(final self::Class* #this) → () →* core::int*
+  return () → core::int* => self::Extension|method(#this);
+static method main() → dynamic {
+  self::Class* c;
+  self::expect(null, let final self::Class* #t2 = c in #t2.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t2));
+  self::expect(null, let final self::Class* #t3 = c in #t3.{core::Object::==}(null) ?{() →* core::int*} null : self::Extension|get#method(#t3));
+  self::expect(null, let final self::Class* #t4 = c in #t4.{core::Object::==}(null) ?{core::int*} null : self::Extension|method(#t4));
+  self::expect(null, let final self::Class* #t5 = c in #t5.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#property(#t5, 42));
+  c = new self::Class::•();
+  self::expect(null, let final self::Class* #t6 = c in #t6.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t6));
+  self::expect(null, let final self::Class* #t7 = c in #t7.{core::Object::==}(null) ?{core::int*} null : self::Extension|method(#t7));
+  () →* core::int* tearOff = let final self::Class* #t8 = c in #t8.{core::Object::==}(null) ?{() →* core::int*} null : self::Extension|get#method(#t8);
+  self::expect(null, tearOff.call());
+  self::expect(42, let final self::Class* #t9 = c in #t9.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#property(#t9, 42));
+  self::expect(42, tearOff.call());
+  self::expect(null, let final self::Class* #t10 = c in #t10.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t10, null));
+  self::expect(42, let final self::Class* #t11 = c in let final core::int* #t12 = self::Extension|get#property(#t11) in #t12.{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t11, 42) : #t12);
+  self::expect(42, let final self::Class* #t13 = c in let final core::int* #t14 = self::Extension|get#property(#t13) in #t14.{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t13, 87) : #t14);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual)) {
+    throw "Mismatch: expected=${expected}, actual=${actual}";
+  }
+}
diff --git a/pkg/front_end/testcases/extensions/null_aware.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/null_aware.dart.type_promotion.expect
new file mode 100644
index 0000000..dee5817
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/null_aware.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/extensions/null_aware.dart:23:5: Context: Write to c@408
+  c = new Class();
+    ^
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 7860276..f788aff 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
@@ -84,7 +84,7 @@
   self::Extension|method<self::Struct*>(struct);
   self::Extension|set#property<self::Struct*>(struct, self::Extension|get#property<self::StructA*>(structA));
   self::Extension|method<self::StructA*>(structA);
-  self::Extension|set#property<self::StructA*>(structA, self::Extension|get#property<self::Struct*>(struct));
+  self::Extension|set#property<self::StructA*>(structA, self::Extension|get#property<self::Struct*>(struct) as{TypeError} self::StructA*);
   self::Extension|method<self::StructB*>(structB);
   self::Extension|set#property<self::StructB*>(structB, self::Extension|get#property<self::StructB*>(structB));
   self::Extension|method<self::Struct*>(new self::Struct::•());
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 7860276..f788aff 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
@@ -84,7 +84,7 @@
   self::Extension|method<self::Struct*>(struct);
   self::Extension|set#property<self::Struct*>(struct, self::Extension|get#property<self::StructA*>(structA));
   self::Extension|method<self::StructA*>(structA);
-  self::Extension|set#property<self::StructA*>(structA, self::Extension|get#property<self::Struct*>(struct));
+  self::Extension|set#property<self::StructA*>(structA, self::Extension|get#property<self::Struct*>(struct) as{TypeError} self::StructA*);
   self::Extension|method<self::StructB*>(structB);
   self::Extension|set#property<self::StructB*>(structB, self::Extension|get#property<self::StructB*>(structB));
   self::Extension|method<self::Struct*>(new self::Struct::•());
diff --git a/pkg/front_end/testcases/extensions/unnamed_extensions.dart b/pkg/front_end/testcases/extensions/unnamed_extensions.dart
new file mode 100644
index 0000000..d425a9f
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/unnamed_extensions.dart
@@ -0,0 +1,115 @@
+// 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 Class1 {
+  int field;
+
+  Class1(this.field);
+
+  String toString() => 'Class1($field)';
+}
+
+class Class2 {
+  int field;
+
+  Class2(this.field);
+
+  String toString() => 'Class2($field)';
+}
+
+extension on Class1 {
+  int method() {
+    print('Extension1.method on $this');
+    return field;
+  }
+  int genericMethod<T extends num>(T t) {
+    print('Extension1.genericMethod<$T>($t) on $this');
+    return field + t;
+  }
+  int get property {
+    print('Extension1.property get on $this');
+    return field;
+  }
+  set property(int value) {
+    field = value;
+    print('Extension1.property set($value) on $this');
+    value++;
+  }
+}
+
+
+extension on Class2 {
+  int method() {
+    print('Extension2.method on $this');
+    return field + 3;
+  }
+  int genericMethod<T extends num>(T t) {
+    print('Extension2.genericMethod<$T>($t) on $this');
+    return field + t + 4;
+  }
+  int get property {
+    print('Extension2.property get on $this');
+    return field + 5;
+  }
+  set property(int value) {
+    print('Extension2.property set($value) on $this');
+    value++;
+    field = value;
+  }
+}
+
+main() {
+  testExtension1();
+  testExtension2();
+}
+
+testExtension1() {
+  Class1 c0 = new Class1(0);
+  Class1 c1 = new Class1(1);
+  expect(0, c0.method());
+  expect(1, c1.method());
+  expect(1, c1?.method());
+  expect(42, c0.genericMethod(42));
+  expect(43, c0.genericMethod<num>(43));
+  expect(88, c1.genericMethod(87));
+  expect(89, c1.genericMethod<num>(88));
+  expect(0, c0.property);
+  expect(0, c0?.property);
+  expect(42, c0.property = 42);
+  expect(1, c1.property);
+  expect(87, c0.property = 87);
+  expect(27, c0.property = c1.property = 27);
+  expect(37, c1.property = c0.property = 37);
+  expect(77, c1.property = c0.property = c1.property = 77);
+  expect(67, c0.property = c1.property = c0.property = 67);
+}
+
+testExtension2() {
+  Class2 c0 = new Class2(0);
+  Class2 c1 = new Class2(1);
+  expect(3, c0.method());
+  expect(3, c0?.method());
+  expect(4, c1.method());
+  expect(46, c0.genericMethod(42));
+  expect(47, c0.genericMethod<num>(43));
+  expect(92, c1.genericMethod(87));
+  expect(93, c1.genericMethod<num>(88));
+  expect(5, c0.property);
+  expect(5, c0?.property);
+  expect(42, c0.property = 42);
+  expect(48, c0.property);
+  expect(6, c1.property);
+  expect(43, c1.property = 43);
+  expect(49, c1.property);
+  expect(49, c0.property = c1.property);
+  expect(55, c1.property = c0.property);
+  expect(61, c1.property = c0.property = c1.property);
+  expect(67, c0.property = c1.property = c0.property);
+}
+
+expect(expected, actual) {
+  if (expected != actual) {
+    throw 'Mismatch: expected=$expected, actual=$actual';
+  }
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.outline.expect b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.outline.expect
new file mode 100644
index 0000000..cc9bdfa
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.outline.expect
@@ -0,0 +1,66 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  field core::int* field;
+  constructor •(core::int* field) → self::Class1*
+    ;
+  method toString() → core::String*
+    ;
+}
+class Class2 extends core::Object {
+  field core::int* field;
+  constructor •(core::int* field) → self::Class2*
+    ;
+  method toString() → core::String*
+    ;
+}
+extension _extension#0 on self::Class1* {
+  method method = self::_extension#0|method;
+  tearoff method = self::_extension#0|get#method;
+  method genericMethod = self::_extension#0|genericMethod;
+  tearoff genericMethod = self::_extension#0|get#genericMethod;
+  get property = self::_extension#0|get#property;
+  set property = self::_extension#0|set#property;
+}
+extension _extension#1 on self::Class2* {
+  method method = self::_extension#1|method;
+  tearoff method = self::_extension#1|get#method;
+  method genericMethod = self::_extension#1|genericMethod;
+  tearoff genericMethod = self::_extension#1|get#genericMethod;
+  get property = self::_extension#1|get#property;
+  set property = self::_extension#1|set#property;
+}
+static method _extension#0|method(final self::Class1* #this) → core::int*
+  ;
+static method _extension#0|get#method(final self::Class1* #this) → () →* core::int*
+  return () → core::int* => self::_extension#0|method(#this);
+static method _extension#0|genericMethod<T extends core::num* = dynamic>(final self::Class1* #this, self::_extension#0|genericMethod::T* t) → core::int*
+  ;
+static method _extension#0|get#genericMethod(final self::Class1* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
+  return <T extends core::num* = dynamic>(T* t) → core::int* => self::_extension#0|genericMethod<T*>(#this, t);
+static method _extension#0|get#property(final self::Class1* #this) → core::int*
+  ;
+static method _extension#0|set#property(final self::Class1* #this, core::int* value) → void
+  ;
+static method _extension#1|method(final self::Class2* #this) → core::int*
+  ;
+static method _extension#1|get#method(final self::Class2* #this) → () →* core::int*
+  return () → core::int* => self::_extension#1|method(#this);
+static method _extension#1|genericMethod<T extends core::num* = dynamic>(final self::Class2* #this, self::_extension#1|genericMethod::T* t) → core::int*
+  ;
+static method _extension#1|get#genericMethod(final self::Class2* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
+  return <T extends core::num* = dynamic>(T* t) → core::int* => self::_extension#1|genericMethod<T*>(#this, t);
+static method _extension#1|get#property(final self::Class2* #this) → core::int*
+  ;
+static method _extension#1|set#property(final self::Class2* #this, core::int* value) → void
+  ;
+static method main() → dynamic
+  ;
+static method testExtension1() → dynamic
+  ;
+static method testExtension2() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.expect b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.expect
new file mode 100644
index 0000000..ec79050
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.expect
@@ -0,0 +1,133 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  field core::int* field;
+  constructor •(core::int* field) → self::Class1*
+    : self::Class1::field = field, super core::Object::•()
+    ;
+  method toString() → core::String*
+    return "Class1(${this.{self::Class1::field}})";
+}
+class Class2 extends core::Object {
+  field core::int* field;
+  constructor •(core::int* field) → self::Class2*
+    : self::Class2::field = field, super core::Object::•()
+    ;
+  method toString() → core::String*
+    return "Class2(${this.{self::Class2::field}})";
+}
+extension _extension#0 on self::Class1* {
+  method method = self::_extension#0|method;
+  tearoff method = self::_extension#0|get#method;
+  method genericMethod = self::_extension#0|genericMethod;
+  tearoff genericMethod = self::_extension#0|get#genericMethod;
+  get property = self::_extension#0|get#property;
+  set property = self::_extension#0|set#property;
+}
+extension _extension#1 on self::Class2* {
+  method method = self::_extension#1|method;
+  tearoff method = self::_extension#1|get#method;
+  method genericMethod = self::_extension#1|genericMethod;
+  tearoff genericMethod = self::_extension#1|get#genericMethod;
+  get property = self::_extension#1|get#property;
+  set property = self::_extension#1|set#property;
+}
+static method _extension#0|method(final self::Class1* #this) → core::int* {
+  core::print("Extension1.method on ${#this}");
+  return #this.{self::Class1::field};
+}
+static method _extension#0|get#method(final self::Class1* #this) → () →* core::int*
+  return () → core::int* => self::_extension#0|method(#this);
+static method _extension#0|genericMethod<T extends core::num* = dynamic>(final self::Class1* #this, self::_extension#0|genericMethod::T* t) → core::int* {
+  core::print("Extension1.genericMethod<${self::_extension#0|genericMethod::T*}>(${t}) on ${#this}");
+  return #this.{self::Class1::field}.{core::num::+}(t) as{TypeError} core::int*;
+}
+static method _extension#0|get#genericMethod(final self::Class1* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
+  return <T extends core::num* = dynamic>(T* t) → core::int* => self::_extension#0|genericMethod<T*>(#this, t);
+static method _extension#0|get#property(final self::Class1* #this) → core::int* {
+  core::print("Extension1.property get on ${#this}");
+  return #this.{self::Class1::field};
+}
+static method _extension#0|set#property(final self::Class1* #this, core::int* value) → core::int* {
+  final core::int* #t1 = value;
+  #this.{self::Class1::field} = value;
+  core::print("Extension1.property set(${value}) on ${#this}");
+  value = value.{core::num::+}(1);
+  return #t1;
+}
+static method _extension#1|method(final self::Class2* #this) → core::int* {
+  core::print("Extension2.method on ${#this}");
+  return #this.{self::Class2::field}.{core::num::+}(3);
+}
+static method _extension#1|get#method(final self::Class2* #this) → () →* core::int*
+  return () → core::int* => self::_extension#1|method(#this);
+static method _extension#1|genericMethod<T extends core::num* = dynamic>(final self::Class2* #this, self::_extension#1|genericMethod::T* t) → core::int* {
+  core::print("Extension2.genericMethod<${self::_extension#1|genericMethod::T*}>(${t}) on ${#this}");
+  return #this.{self::Class2::field}.{core::num::+}(t).{core::num::+}(4) as{TypeError} core::int*;
+}
+static method _extension#1|get#genericMethod(final self::Class2* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
+  return <T extends core::num* = dynamic>(T* t) → core::int* => self::_extension#1|genericMethod<T*>(#this, t);
+static method _extension#1|get#property(final self::Class2* #this) → core::int* {
+  core::print("Extension2.property get on ${#this}");
+  return #this.{self::Class2::field}.{core::num::+}(5);
+}
+static method _extension#1|set#property(final self::Class2* #this, core::int* value) → core::int* {
+  final core::int* #t2 = value;
+  core::print("Extension2.property set(${value}) on ${#this}");
+  value = value.{core::num::+}(1);
+  #this.{self::Class2::field} = value;
+  return #t2;
+}
+static method main() → dynamic {
+  self::testExtension1();
+  self::testExtension2();
+}
+static method testExtension1() → dynamic {
+  self::Class1* c0 = new self::Class1::•(0);
+  self::Class1* c1 = new self::Class1::•(1);
+  self::expect(0, self::_extension#0|method(c0));
+  self::expect(1, self::_extension#0|method(c1));
+  self::expect(1, let final self::Class1* #t3 = c1 in #t3.{core::Object::==}(null) ?{core::int*} null : self::_extension#0|method(#t3));
+  self::expect(42, self::_extension#0|genericMethod<core::int*>(c0, 42));
+  self::expect(43, self::_extension#0|genericMethod<core::num*>(c0, 43));
+  self::expect(88, self::_extension#0|genericMethod<core::int*>(c1, 87));
+  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* #t4 = c0 in #t4.{core::Object::==}(null) ?{core::int*} null : self::_extension#0|get#property(#t4));
+  self::expect(42, self::_extension#0|set#property(c0, 42));
+  self::expect(1, self::_extension#0|get#property(c1));
+  self::expect(87, self::_extension#0|set#property(c0, 87));
+  self::expect(27, self::_extension#0|set#property(c0, self::_extension#0|set#property(c1, 27)));
+  self::expect(37, self::_extension#0|set#property(c1, self::_extension#0|set#property(c0, 37)));
+  self::expect(77, self::_extension#0|set#property(c1, self::_extension#0|set#property(c0, self::_extension#0|set#property(c1, 77))));
+  self::expect(67, self::_extension#0|set#property(c0, self::_extension#0|set#property(c1, self::_extension#0|set#property(c0, 67))));
+}
+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* #t5 = c0 in #t5.{core::Object::==}(null) ?{core::int*} null : self::_extension#1|method(#t5));
+  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* #t6 = c0 in #t6.{core::Object::==}(null) ?{core::int*} null : self::_extension#1|get#property(#t6));
+  self::expect(42, self::_extension#1|set#property(c0, 42));
+  self::expect(48, self::_extension#1|get#property(c0));
+  self::expect(6, self::_extension#1|get#property(c1));
+  self::expect(43, self::_extension#1|set#property(c1, 43));
+  self::expect(49, self::_extension#1|get#property(c1));
+  self::expect(49, self::_extension#1|set#property(c0, self::_extension#1|get#property(c1)));
+  self::expect(55, self::_extension#1|set#property(c1, self::_extension#1|get#property(c0)));
+  self::expect(61, self::_extension#1|set#property(c1, self::_extension#1|set#property(c0, self::_extension#1|get#property(c1))));
+  self::expect(67, self::_extension#1|set#property(c0, self::_extension#1|set#property(c1, self::_extension#1|get#property(c0))));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual)) {
+    throw "Mismatch: expected=${expected}, actual=${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
new file mode 100644
index 0000000..ec79050
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.transformed.expect
@@ -0,0 +1,133 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  field core::int* field;
+  constructor •(core::int* field) → self::Class1*
+    : self::Class1::field = field, super core::Object::•()
+    ;
+  method toString() → core::String*
+    return "Class1(${this.{self::Class1::field}})";
+}
+class Class2 extends core::Object {
+  field core::int* field;
+  constructor •(core::int* field) → self::Class2*
+    : self::Class2::field = field, super core::Object::•()
+    ;
+  method toString() → core::String*
+    return "Class2(${this.{self::Class2::field}})";
+}
+extension _extension#0 on self::Class1* {
+  method method = self::_extension#0|method;
+  tearoff method = self::_extension#0|get#method;
+  method genericMethod = self::_extension#0|genericMethod;
+  tearoff genericMethod = self::_extension#0|get#genericMethod;
+  get property = self::_extension#0|get#property;
+  set property = self::_extension#0|set#property;
+}
+extension _extension#1 on self::Class2* {
+  method method = self::_extension#1|method;
+  tearoff method = self::_extension#1|get#method;
+  method genericMethod = self::_extension#1|genericMethod;
+  tearoff genericMethod = self::_extension#1|get#genericMethod;
+  get property = self::_extension#1|get#property;
+  set property = self::_extension#1|set#property;
+}
+static method _extension#0|method(final self::Class1* #this) → core::int* {
+  core::print("Extension1.method on ${#this}");
+  return #this.{self::Class1::field};
+}
+static method _extension#0|get#method(final self::Class1* #this) → () →* core::int*
+  return () → core::int* => self::_extension#0|method(#this);
+static method _extension#0|genericMethod<T extends core::num* = dynamic>(final self::Class1* #this, self::_extension#0|genericMethod::T* t) → core::int* {
+  core::print("Extension1.genericMethod<${self::_extension#0|genericMethod::T*}>(${t}) on ${#this}");
+  return #this.{self::Class1::field}.{core::num::+}(t) as{TypeError} core::int*;
+}
+static method _extension#0|get#genericMethod(final self::Class1* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
+  return <T extends core::num* = dynamic>(T* t) → core::int* => self::_extension#0|genericMethod<T*>(#this, t);
+static method _extension#0|get#property(final self::Class1* #this) → core::int* {
+  core::print("Extension1.property get on ${#this}");
+  return #this.{self::Class1::field};
+}
+static method _extension#0|set#property(final self::Class1* #this, core::int* value) → core::int* {
+  final core::int* #t1 = value;
+  #this.{self::Class1::field} = value;
+  core::print("Extension1.property set(${value}) on ${#this}");
+  value = value.{core::num::+}(1);
+  return #t1;
+}
+static method _extension#1|method(final self::Class2* #this) → core::int* {
+  core::print("Extension2.method on ${#this}");
+  return #this.{self::Class2::field}.{core::num::+}(3);
+}
+static method _extension#1|get#method(final self::Class2* #this) → () →* core::int*
+  return () → core::int* => self::_extension#1|method(#this);
+static method _extension#1|genericMethod<T extends core::num* = dynamic>(final self::Class2* #this, self::_extension#1|genericMethod::T* t) → core::int* {
+  core::print("Extension2.genericMethod<${self::_extension#1|genericMethod::T*}>(${t}) on ${#this}");
+  return #this.{self::Class2::field}.{core::num::+}(t).{core::num::+}(4) as{TypeError} core::int*;
+}
+static method _extension#1|get#genericMethod(final self::Class2* #this) → <T extends core::num* = dynamic>(T*) →* core::int*
+  return <T extends core::num* = dynamic>(T* t) → core::int* => self::_extension#1|genericMethod<T*>(#this, t);
+static method _extension#1|get#property(final self::Class2* #this) → core::int* {
+  core::print("Extension2.property get on ${#this}");
+  return #this.{self::Class2::field}.{core::num::+}(5);
+}
+static method _extension#1|set#property(final self::Class2* #this, core::int* value) → core::int* {
+  final core::int* #t2 = value;
+  core::print("Extension2.property set(${value}) on ${#this}");
+  value = value.{core::num::+}(1);
+  #this.{self::Class2::field} = value;
+  return #t2;
+}
+static method main() → dynamic {
+  self::testExtension1();
+  self::testExtension2();
+}
+static method testExtension1() → dynamic {
+  self::Class1* c0 = new self::Class1::•(0);
+  self::Class1* c1 = new self::Class1::•(1);
+  self::expect(0, self::_extension#0|method(c0));
+  self::expect(1, self::_extension#0|method(c1));
+  self::expect(1, let final self::Class1* #t3 = c1 in #t3.{core::Object::==}(null) ?{core::int*} null : self::_extension#0|method(#t3));
+  self::expect(42, self::_extension#0|genericMethod<core::int*>(c0, 42));
+  self::expect(43, self::_extension#0|genericMethod<core::num*>(c0, 43));
+  self::expect(88, self::_extension#0|genericMethod<core::int*>(c1, 87));
+  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* #t4 = c0 in #t4.{core::Object::==}(null) ?{core::int*} null : self::_extension#0|get#property(#t4));
+  self::expect(42, self::_extension#0|set#property(c0, 42));
+  self::expect(1, self::_extension#0|get#property(c1));
+  self::expect(87, self::_extension#0|set#property(c0, 87));
+  self::expect(27, self::_extension#0|set#property(c0, self::_extension#0|set#property(c1, 27)));
+  self::expect(37, self::_extension#0|set#property(c1, self::_extension#0|set#property(c0, 37)));
+  self::expect(77, self::_extension#0|set#property(c1, self::_extension#0|set#property(c0, self::_extension#0|set#property(c1, 77))));
+  self::expect(67, self::_extension#0|set#property(c0, self::_extension#0|set#property(c1, self::_extension#0|set#property(c0, 67))));
+}
+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* #t5 = c0 in #t5.{core::Object::==}(null) ?{core::int*} null : self::_extension#1|method(#t5));
+  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* #t6 = c0 in #t6.{core::Object::==}(null) ?{core::int*} null : self::_extension#1|get#property(#t6));
+  self::expect(42, self::_extension#1|set#property(c0, 42));
+  self::expect(48, self::_extension#1|get#property(c0));
+  self::expect(6, self::_extension#1|get#property(c1));
+  self::expect(43, self::_extension#1|set#property(c1, 43));
+  self::expect(49, self::_extension#1|get#property(c1));
+  self::expect(49, self::_extension#1|set#property(c0, self::_extension#1|get#property(c1)));
+  self::expect(55, self::_extension#1|set#property(c1, self::_extension#1|get#property(c0)));
+  self::expect(61, self::_extension#1|set#property(c1, self::_extension#1|set#property(c0, self::_extension#1|get#property(c1))));
+  self::expect(67, self::_extension#1|set#property(c0, self::_extension#1|set#property(c1, self::_extension#1|get#property(c0))));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual)) {
+    throw "Mismatch: expected=${expected}, actual=${actual}";
+  }
+}
diff --git a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.type_promotion.expect
new file mode 100644
index 0000000..a2934e5
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/extensions/unnamed_extensions.dart:37:10: Context: Write to value@744
+    value++;
+         ^^
+pkg/front_end/testcases/extensions/unnamed_extensions.dart:57:10: Context: Write to value@1195
+    value++;
+         ^^
diff --git a/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.expect b/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.expect
index 18047a8..023576c 100644
--- a/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.expect
+++ b/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.expect
@@ -25,9 +25,9 @@
     @#C1 core::String* localWithInitializer = "hello";
     @#C1 @#C2 dynamic localGroupPart1;
     @#C1 @#C2 dynamic localGroupPart2;
-    function naebdyr(@#C1 dynamic nestedFormal) → core::Null*
+    function naebdyr(@#C1 dynamic nestedFormal) → core::Null?
       return null;
-    (dynamic) →* core::Null* roedmus = (@#C1 dynamic closureFormal) → core::Null* => null;
+    (dynamic) →* core::Null? roedmus = (@#C1 dynamic closureFormal) → core::Null? => null;
   }
   method hest({@#C1 dynamic named = #C3}) → dynamic
     return null;
diff --git a/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.transformed.expect b/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.transformed.expect
index 18047a8..023576c 100644
--- a/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.transformed.expect
@@ -25,9 +25,9 @@
     @#C1 core::String* localWithInitializer = "hello";
     @#C1 @#C2 dynamic localGroupPart1;
     @#C1 @#C2 dynamic localGroupPart2;
-    function naebdyr(@#C1 dynamic nestedFormal) → core::Null*
+    function naebdyr(@#C1 dynamic nestedFormal) → core::Null?
       return null;
-    (dynamic) →* core::Null* roedmus = (@#C1 dynamic closureFormal) → core::Null* => null;
+    (dynamic) →* core::Null? roedmus = (@#C1 dynamic closureFormal) → core::Null? => null;
   }
   method hest({@#C1 dynamic named = #C3}) → dynamic
     return null;
diff --git a/pkg/front_end/testcases/general/async_nested.dart.strong.expect b/pkg/front_end/testcases/general/async_nested.dart.strong.expect
index c01b082..5c3da0c 100644
--- a/pkg/front_end/testcases/general/async_nested.dart.strong.expect
+++ b/pkg/front_end/testcases/general/async_nested.dart.strong.expect
@@ -11,10 +11,10 @@
   constructor •(core::String* name, [core::List<self::Node*>* nested = #C1]) → self::Node*
     : self::Node::name = name, self::Node::nested = nested, super core::Object::•() {}
   method toString() → core::String*
-    return "<${this.{self::Node::name}}:[${let final core::List<self::Node*>* #t1 = this.{self::Node::nested} in #t1.==(null) ?{core::String*} null : #t1.{core::Iterable::join}(", ")}]>";
+    return "<${this.{self::Node::name}}:[${let final core::List<self::Node*>* #t1 = this.{self::Node::nested} in #t1.{core::List::==}(null) ?{core::String*} null : #t1.{core::Iterable::join}(", ")}]>";
   method toSimpleString() → dynamic {
-    core::Iterable<dynamic>* tmp = let final core::List<self::Node*>* #t2 = this.{self::Node::nested} in #t2.==(null) ?{core::Iterable<dynamic>*} null : #t2.{core::Iterable::map}<dynamic>((self::Node* child) → dynamic => child.{self::Node::toSimpleString}());
-    return "${this.{self::Node::name}} ${let final core::Iterable<dynamic>* #t3 = tmp in #t3.==(null) ?{core::String*} null : #t3.{core::Iterable::join}(" ")}".{core::String::trim}();
+    core::Iterable<dynamic>* tmp = let final core::List<self::Node*>* #t2 = this.{self::Node::nested} in #t2.{core::List::==}(null) ?{core::Iterable<dynamic>*} null : #t2.{core::Iterable::map}<dynamic>((self::Node* child) → dynamic => child.{self::Node::toSimpleString}());
+    return "${this.{self::Node::name}} ${let final core::Iterable<dynamic>* #t3 = tmp in #t3.{core::Object::==}(null) ?{core::String*} null : #t3.{core::Iterable::join}(" ")}".{core::String::trim}();
   }
 }
 static method main() → void async {
diff --git a/pkg/front_end/testcases/general/async_nested.dart.strong.transformed.expect b/pkg/front_end/testcases/general/async_nested.dart.strong.transformed.expect
index 730f857..256ef3f 100644
--- a/pkg/front_end/testcases/general/async_nested.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/async_nested.dart.strong.transformed.expect
@@ -11,10 +11,10 @@
   constructor •(core::String* name, [core::List<self::Node*>* nested = #C1]) → self::Node*
     : self::Node::name = name, self::Node::nested = nested, super core::Object::•() {}
   method toString() → core::String*
-    return "<${this.{self::Node::name}}:[${let final core::List<self::Node*>* #t1 = this.{self::Node::nested} in #t1.==(null) ?{core::String*} null : #t1.{core::Iterable::join}(", ")}]>";
+    return "<${this.{self::Node::name}}:[${let final core::List<self::Node*>* #t1 = this.{self::Node::nested} in #t1.{core::List::==}(null) ?{core::String*} null : #t1.{core::Iterable::join}(", ")}]>";
   method toSimpleString() → dynamic {
-    core::Iterable<dynamic>* tmp = let final core::List<self::Node*>* #t2 = this.{self::Node::nested} in #t2.==(null) ?{core::Iterable<dynamic>*} null : #t2.{core::Iterable::map}<dynamic>((self::Node* child) → dynamic => child.{self::Node::toSimpleString}());
-    return "${this.{self::Node::name}} ${let final core::Iterable<dynamic>* #t3 = tmp in #t3.==(null) ?{core::String*} null : #t3.{core::Iterable::join}(" ")}".{core::String::trim}();
+    core::Iterable<dynamic>* tmp = let final core::List<self::Node*>* #t2 = this.{self::Node::nested} in #t2.{core::List::==}(null) ?{core::Iterable<dynamic>*} null : #t2.{core::Iterable::map}<dynamic>((self::Node* child) → dynamic => child.{self::Node::toSimpleString}());
+    return "${this.{self::Node::name}} ${let final core::Iterable<dynamic>* #t3 = tmp in #t3.{core::Object::==}(null) ?{core::String*} null : #t3.{core::Iterable::join}(" ")}".{core::String::trim}();
   }
 }
 static method main() → void /* originally async */ {
diff --git a/pkg/front_end/testcases/general/bug33099.dart.strong.expect b/pkg/front_end/testcases/general/bug33099.dart.strong.expect
index 537c6ae..98cc4a6 100644
--- a/pkg/front_end/testcases/general/bug33099.dart.strong.expect
+++ b/pkg/front_end/testcases/general/bug33099.dart.strong.expect
@@ -30,7 +30,7 @@
 static const field self::_FailingTest* failingTest = #C1;
 static method main() → dynamic {
   mir::ClassMirror* classMirror = mir::reflectClass(self::MyTest2*);
-  classMirror.{mir::ClassMirror::instanceMembers}.{core::Map::forEach}((core::Symbol* symbol, mir::MethodMirror* memberMirror) → core::Null* {
+  classMirror.{mir::ClassMirror::instanceMembers}.{core::Map::forEach}((core::Symbol* symbol, mir::MethodMirror* memberMirror) → core::Null? {
     if(memberMirror.{mir::DeclarationMirror::simpleName}.{core::Symbol::==}(#C2)) {
       core::print(memberMirror);
       core::print(self::_hasFailingTestAnnotation(memberMirror));
diff --git a/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect
index 0a95528..f56cb2a 100644
--- a/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect
@@ -32,7 +32,7 @@
 static const field self::_FailingTest* failingTest = #C1;
 static method main() → dynamic {
   mir::ClassMirror* classMirror = mir::reflectClass(self::MyTest2*);
-  classMirror.{mir::ClassMirror::instanceMembers}.{core::Map::forEach}((core::Symbol* symbol, mir::MethodMirror* memberMirror) → core::Null* {
+  classMirror.{mir::ClassMirror::instanceMembers}.{core::Map::forEach}((core::Symbol* symbol, mir::MethodMirror* memberMirror) → core::Null? {
     if(memberMirror.{mir::DeclarationMirror::simpleName}.{core::Symbol::==}(#C2)) {
       core::print(memberMirror);
       core::print(self::_hasFailingTestAnnotation(memberMirror));
diff --git a/pkg/front_end/testcases/general/bug33298.dart.strong.expect b/pkg/front_end/testcases/general/bug33298.dart.strong.expect
index 57354a6..57e3d95 100644
--- a/pkg/front_end/testcases/general/bug33298.dart.strong.expect
+++ b/pkg/front_end/testcases/general/bug33298.dart.strong.expect
@@ -43,6 +43,6 @@
   core::List<core::String*>* list6 = <core::String*>["a", "b", "c"].{core::Iterable::map}<dynamic>(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general/bug33298.dart:28:44: Error: The argument type 'T Function<T>(T)' can't be assigned to the parameter type 'dynamic Function(String)'.
 Try changing the type of the parameter, or casting the argument to 'dynamic Function(String)'.
   List<String> list6 = ['a', 'b', 'c'].map(c).toList();
-                                           ^" in (let final self::C* #t4 = c in #t4.==(null) ?{<T extends core::Object* = dynamic>(self::C::call::T*) →* self::C::call::T*} null : #t4.{self::C::call}) as{TypeError} (core::String*) →* dynamic).{core::Iterable::toList}() as{TypeError} core::List<core::String*>*;
+                                           ^" in (let final self::C* #t4 = c in #t4.==(null) ?{<T extends core::Object* = dynamic>(T*) →* T*} null : #t4.{self::C::call}) as{TypeError} (core::String*) →* dynamic).{core::Iterable::toList}() as{TypeError} core::List<core::String*>*;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/bug33298.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bug33298.dart.strong.transformed.expect
index 57354a6..57e3d95 100644
--- a/pkg/front_end/testcases/general/bug33298.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33298.dart.strong.transformed.expect
@@ -43,6 +43,6 @@
   core::List<core::String*>* list6 = <core::String*>["a", "b", "c"].{core::Iterable::map}<dynamic>(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general/bug33298.dart:28:44: Error: The argument type 'T Function<T>(T)' can't be assigned to the parameter type 'dynamic Function(String)'.
 Try changing the type of the parameter, or casting the argument to 'dynamic Function(String)'.
   List<String> list6 = ['a', 'b', 'c'].map(c).toList();
-                                           ^" in (let final self::C* #t4 = c in #t4.==(null) ?{<T extends core::Object* = dynamic>(self::C::call::T*) →* self::C::call::T*} null : #t4.{self::C::call}) as{TypeError} (core::String*) →* dynamic).{core::Iterable::toList}() as{TypeError} core::List<core::String*>*;
+                                           ^" in (let final self::C* #t4 = c in #t4.==(null) ?{<T extends core::Object* = dynamic>(T*) →* T*} null : #t4.{self::C::call}) as{TypeError} (core::String*) →* dynamic).{core::Iterable::toList}() as{TypeError} core::List<core::String*>*;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/bug37476.dart.strong.expect b/pkg/front_end/testcases/general/bug37476.dart.strong.expect
index 49098e1..cd1a2ae 100644
--- a/pkg/front_end/testcases/general/bug37476.dart.strong.expect
+++ b/pkg/front_end/testcases/general/bug37476.dart.strong.expect
@@ -8,7 +8,7 @@
     ;
   method foo() → <S extends self::A::T* = dynamic>(S*) →* void {
     core::print("foo: T = ${self::A::T*}");
-    return <S extends self::A::T* = self::A::T*>(S* a) → core::Null* {};
+    return <S extends self::A::T* = self::A::T*>(S* a) → core::Null? {};
   }
 }
 class B<T extends core::num* = core::num*> extends core::Object {
@@ -17,7 +17,7 @@
     ;
   method foo() → (self::B::T*) →* void {
     core::print("foo: T = ${self::B::T*}");
-    return (self::B::T* a) → core::Null* {};
+    return (self::B::T* a) → core::Null? {};
   }
 }
 static field self::A<core::num*>* a = new self::A::•<core::int*>();
diff --git a/pkg/front_end/testcases/general/bug37476.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bug37476.dart.strong.transformed.expect
index 49098e1..cd1a2ae 100644
--- a/pkg/front_end/testcases/general/bug37476.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bug37476.dart.strong.transformed.expect
@@ -8,7 +8,7 @@
     ;
   method foo() → <S extends self::A::T* = dynamic>(S*) →* void {
     core::print("foo: T = ${self::A::T*}");
-    return <S extends self::A::T* = self::A::T*>(S* a) → core::Null* {};
+    return <S extends self::A::T* = self::A::T*>(S* a) → core::Null? {};
   }
 }
 class B<T extends core::num* = core::num*> extends core::Object {
@@ -17,7 +17,7 @@
     ;
   method foo() → (self::B::T*) →* void {
     core::print("foo: T = ${self::B::T*}");
-    return (self::B::T* a) → core::Null* {};
+    return (self::B::T* a) → core::Null? {};
   }
 }
 static field self::A<core::num*>* a = new self::A::•<core::int*>();
diff --git a/pkg/front_end/testcases/general/compound_binary_implicit_as.dart b/pkg/front_end/testcases/general/compound_binary_implicit_as.dart
new file mode 100644
index 0000000..ea6ab25
--- /dev/null
+++ b/pkg/front_end/testcases/general/compound_binary_implicit_as.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.
+
+class A {}
+
+class B extends A {
+  A operator +(B b) => new C();
+}
+
+class C extends A {}
+
+main() {
+  Map<int, B> map = {0: new B()};
+  try {
+    map[0] += new B();
+    throw 'Expected type error';
+  } catch (_) {}
+}
diff --git a/pkg/front_end/testcases/general/compound_binary_implicit_as.dart.outline.expect b/pkg/front_end/testcases/general/compound_binary_implicit_as.dart.outline.expect
new file mode 100644
index 0000000..36ce691
--- /dev/null
+++ b/pkg/front_end/testcases/general/compound_binary_implicit_as.dart.outline.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    ;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B*
+    ;
+  operator +(self::B* b) → self::A*
+    ;
+}
+class C extends self::A {
+  synthetic constructor •() → self::C*
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/compound_binary_implicit_as.dart.strong.expect b/pkg/front_end/testcases/general/compound_binary_implicit_as.dart.strong.expect
new file mode 100644
index 0000000..3781401
--- /dev/null
+++ b/pkg/front_end/testcases/general/compound_binary_implicit_as.dart.strong.expect
@@ -0,0 +1,30 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+  operator +(self::B* b) → self::A*
+    return new self::C::•();
+}
+class C extends self::A {
+  synthetic constructor •() → self::C*
+    : super self::A::•()
+    ;
+}
+static method main() → dynamic {
+  core::Map<core::int*, self::B*>* map = <core::int*, self::B*>{0: new self::B::•()};
+  try {
+    let final core::Map<core::int*, self::B*>* #t1 = map in let final core::int* #t2 = 0 in #t1.{core::Map::[]=}(#t2, #t1.{core::Map::[]}(#t2).{self::B::+}(new self::B::•()) as{TypeError} self::B*);
+    throw "Expected type error";
+  }
+  on dynamic catch(final dynamic _) {
+  }
+}
diff --git a/pkg/front_end/testcases/general/compound_binary_implicit_as.dart.strong.transformed.expect b/pkg/front_end/testcases/general/compound_binary_implicit_as.dart.strong.transformed.expect
new file mode 100644
index 0000000..3781401
--- /dev/null
+++ b/pkg/front_end/testcases/general/compound_binary_implicit_as.dart.strong.transformed.expect
@@ -0,0 +1,30 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+  operator +(self::B* b) → self::A*
+    return new self::C::•();
+}
+class C extends self::A {
+  synthetic constructor •() → self::C*
+    : super self::A::•()
+    ;
+}
+static method main() → dynamic {
+  core::Map<core::int*, self::B*>* map = <core::int*, self::B*>{0: new self::B::•()};
+  try {
+    let final core::Map<core::int*, self::B*>* #t1 = map in let final core::int* #t2 = 0 in #t1.{core::Map::[]=}(#t2, #t1.{core::Map::[]}(#t2).{self::B::+}(new self::B::•()) as{TypeError} self::B*);
+    throw "Expected type error";
+  }
+  on dynamic catch(final dynamic _) {
+  }
+}
diff --git a/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.expect b/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.expect
index 9b8bc6d..45d397e 100644
--- a/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.expect
@@ -26,5 +26,5 @@
 }
 
 constants  {
-  #C1 = self::_Y<core::Null*> {}
+  #C1 = self::_Y<core::Null?> {}
 }
diff --git a/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.transformed.expect
index 9b8bc6d..45d397e 100644
--- a/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.transformed.expect
@@ -26,5 +26,5 @@
 }
 
 constants  {
-  #C1 = self::_Y<core::Null*> {}
+  #C1 = self::_Y<core::Null?> {}
 }
diff --git a/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.expect b/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.expect
index 5f32797..a7c5eb0 100644
--- a/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.expect
@@ -1208,10 +1208,10 @@
   core::Map<dynamic, dynamic>* map11 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:109:70: Error: Expected ':' after this.
   Map<dynamic, dynamic> map11 = {if (oracle(\"foo\")) \"bar\": 3.14 else 42};
                                                                      ^": null};
-  core::Map<<BottomType>, core::Null*>* map12 = <<BottomType>, core::Null*>{invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:110:35: Error: Expected ':' after this.
+  core::Map<<BottomType>, core::Null?>* map12 = <<BottomType>, core::Null?>{invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:110:35: Error: Expected ':' after this.
   var map12 = {if (oracle(\"foo\")) 42 else \"bar\": 3.14};
                                   ^": null};
-  core::Map<<BottomType>, core::Null*>* map13 = <<BottomType>, core::Null*>{invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:111:52: Error: Expected ':' after this.
+  core::Map<<BottomType>, core::Null?>* map13 = <<BottomType>, core::Null?>{invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:111:52: Error: Expected ':' after this.
   var map13 = {if (oracle(\"foo\")) \"bar\": 3.14 else 42};
                                                    ^": null};
   core::List<core::int*>* list20 = block {
diff --git a/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.transformed.expect
index 7f1ee70..5cc5798 100644
--- a/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.transformed.expect
@@ -1208,10 +1208,10 @@
   core::Map<dynamic, dynamic>* map11 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:109:70: Error: Expected ':' after this.
   Map<dynamic, dynamic> map11 = {if (oracle(\"foo\")) \"bar\": 3.14 else 42};
                                                                      ^": null};
-  core::Map<<BottomType>, core::Null*>* map12 = <<BottomType>, core::Null*>{invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:110:35: Error: Expected ':' after this.
+  core::Map<<BottomType>, core::Null?>* map12 = <<BottomType>, core::Null?>{invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:110:35: Error: Expected ':' after this.
   var map12 = {if (oracle(\"foo\")) 42 else \"bar\": 3.14};
                                   ^": null};
-  core::Map<<BottomType>, core::Null*>* map13 = <<BottomType>, core::Null*>{invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:111:52: Error: Expected ':' after this.
+  core::Map<<BottomType>, core::Null?>* map13 = <<BottomType>, core::Null?>{invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:111:52: Error: Expected ':' after this.
   var map13 = {if (oracle(\"foo\")) \"bar\": 3.14 else 42};
                                                    ^": null};
   core::List<core::int*>* list20 = block {
diff --git a/pkg/front_end/testcases/general/covariant_generic.dart.strong.expect b/pkg/front_end/testcases/general/covariant_generic.dart.strong.expect
index c7bba1c..684ab99 100644
--- a/pkg/front_end/testcases/general/covariant_generic.dart.strong.expect
+++ b/pkg/front_end/testcases/general/covariant_generic.dart.strong.expect
@@ -18,22 +18,22 @@
   }
 }
 static method main() → dynamic {
-  self::Foo<core::int*>* fooInt = new self::Foo::•<core::int*>(1, (core::int* x) → core::Null* {});
+  self::Foo<core::int*>* fooInt = new self::Foo::•<core::int*>(1, (core::int* x) → core::Null? {});
   fooInt.{self::Foo::method}(3);
   fooInt.{self::Foo::setter} = 3;
-  fooInt.{self::Foo::withCallback}((core::int* x) → core::Null* {});
-  fooInt.{self::Foo::withCallback}((core::num* x) → core::Null* {});
+  fooInt.{self::Foo::withCallback}((core::int* x) → core::Null? {});
+  fooInt.{self::Foo::withCallback}((core::num* x) → core::Null? {});
   fooInt.{self::Foo::mutableField} = 3;
-  fooInt.{self::Foo::mutableCallbackField} = (core::int* x) → core::Null* {};
+  fooInt.{self::Foo::mutableCallbackField} = (core::int* x) → core::Null? {};
   self::Foo<core::num*>* fooNum = fooInt;
   fooNum.{self::Foo::method}(3);
   fooNum.{self::Foo::method}(2.5);
   fooNum.{self::Foo::setter} = 3;
   fooNum.{self::Foo::setter} = 2.5;
-  fooNum.{self::Foo::withCallback}((core::num* x) → core::Null* {});
+  fooNum.{self::Foo::withCallback}((core::num* x) → core::Null? {});
   fooNum.{self::Foo::mutableField} = 3;
   fooNum.{self::Foo::mutableField} = 2.5;
   (fooNum.{self::Foo::mutableCallbackField} as{TypeError} (core::num*) →* void).call(3);
   (fooNum.{self::Foo::mutableCallbackField} as{TypeError} (core::num*) →* void).call(2.5);
-  fooNum.{self::Foo::mutableCallbackField} = (core::num* x) → core::Null* {};
+  fooNum.{self::Foo::mutableCallbackField} = (core::num* x) → core::Null? {};
 }
diff --git a/pkg/front_end/testcases/general/covariant_generic.dart.strong.transformed.expect b/pkg/front_end/testcases/general/covariant_generic.dart.strong.transformed.expect
index c7bba1c..684ab99 100644
--- a/pkg/front_end/testcases/general/covariant_generic.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/covariant_generic.dart.strong.transformed.expect
@@ -18,22 +18,22 @@
   }
 }
 static method main() → dynamic {
-  self::Foo<core::int*>* fooInt = new self::Foo::•<core::int*>(1, (core::int* x) → core::Null* {});
+  self::Foo<core::int*>* fooInt = new self::Foo::•<core::int*>(1, (core::int* x) → core::Null? {});
   fooInt.{self::Foo::method}(3);
   fooInt.{self::Foo::setter} = 3;
-  fooInt.{self::Foo::withCallback}((core::int* x) → core::Null* {});
-  fooInt.{self::Foo::withCallback}((core::num* x) → core::Null* {});
+  fooInt.{self::Foo::withCallback}((core::int* x) → core::Null? {});
+  fooInt.{self::Foo::withCallback}((core::num* x) → core::Null? {});
   fooInt.{self::Foo::mutableField} = 3;
-  fooInt.{self::Foo::mutableCallbackField} = (core::int* x) → core::Null* {};
+  fooInt.{self::Foo::mutableCallbackField} = (core::int* x) → core::Null? {};
   self::Foo<core::num*>* fooNum = fooInt;
   fooNum.{self::Foo::method}(3);
   fooNum.{self::Foo::method}(2.5);
   fooNum.{self::Foo::setter} = 3;
   fooNum.{self::Foo::setter} = 2.5;
-  fooNum.{self::Foo::withCallback}((core::num* x) → core::Null* {});
+  fooNum.{self::Foo::withCallback}((core::num* x) → core::Null? {});
   fooNum.{self::Foo::mutableField} = 3;
   fooNum.{self::Foo::mutableField} = 2.5;
   (fooNum.{self::Foo::mutableCallbackField} as{TypeError} (core::num*) →* void).call(3);
   (fooNum.{self::Foo::mutableCallbackField} as{TypeError} (core::num*) →* void).call(2.5);
-  fooNum.{self::Foo::mutableCallbackField} = (core::num* x) → core::Null* {};
+  fooNum.{self::Foo::mutableCallbackField} = (core::num* x) → core::Null? {};
 }
diff --git a/pkg/front_end/testcases/general/export_test.dart b/pkg/front_end/testcases/general/export_test.dart
index a95dbfa..13646cf 100644
--- a/pkg/front_end/testcases/general/export_test.dart
+++ b/pkg/front_end/testcases/general/export_test.dart
@@ -4,10 +4,9 @@
 
 /// Test that exports are serialized in platform.dill.
 
-// Note: "dart:profiler" exports UserTag from "dart:developer". This is
-// somewhat brittle and we should extend this test framework to be able to deal
-// with multiple .dill files.
-import 'dart:profiler' show UserTag;
+// This is somewhat brittle and we should extend this test framework to be
+// able to deal with multiple .dill files.
+import 'dart:developer' show UserTag;
 
 export 'dart:core' show print;
 
diff --git a/pkg/front_end/testcases/general/export_test.dart.outline.expect b/pkg/front_end/testcases/general/export_test.dart.outline.expect
index e337eae..a49370d 100644
--- a/pkg/front_end/testcases/general/export_test.dart.outline.expect
+++ b/pkg/front_end/testcases/general/export_test.dart.outline.expect
@@ -4,7 +4,7 @@
 additionalExports = (core::print)
 
 
-import "dart:profiler";
+import "dart:developer";
 export "dart:core";
 
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/general/export_test.dart.strong.expect b/pkg/front_end/testcases/general/export_test.dart.strong.expect
index 96ce0dd..3f5a303 100644
--- a/pkg/front_end/testcases/general/export_test.dart.strong.expect
+++ b/pkg/front_end/testcases/general/export_test.dart.strong.expect
@@ -5,7 +5,7 @@
 additionalExports = (core::print)
 
 
-import "dart:profiler";
+import "dart:developer";
 export "dart:core";
 
 static method main() → dynamic {
diff --git a/pkg/front_end/testcases/general/export_test.dart.strong.transformed.expect b/pkg/front_end/testcases/general/export_test.dart.strong.transformed.expect
index 96ce0dd..3f5a303 100644
--- a/pkg/front_end/testcases/general/export_test.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/export_test.dart.strong.transformed.expect
@@ -5,7 +5,7 @@
 additionalExports = (core::print)
 
 
-import "dart:profiler";
+import "dart:developer";
 export "dart:core";
 
 static method main() → dynamic {
diff --git a/pkg/front_end/testcases/general/expressions.dart.strong.expect b/pkg/front_end/testcases/general/expressions.dart.strong.expect
index bc4e719..7826eeb 100644
--- a/pkg/front_end/testcases/general/expressions.dart.strong.expect
+++ b/pkg/front_end/testcases/general/expressions.dart.strong.expect
@@ -51,25 +51,25 @@
   core::print(#C2);
   core::print(core::List::•<core::String*>(2).{core::Object::runtimeType});
   self::foo(fisk: "Blorp gulp");
-  function f() → core::Null* {
+  function f() → core::Null? {
     core::print("f was called");
   }
   self::caller(f);
-  self::caller(() → core::Null* {
+  self::caller(() → core::Null? {
     core::print("<anon> was called");
   });
-  function g([dynamic message = #C1]) → core::Null* {
+  function g([dynamic message = #C1]) → core::Null? {
     core::print(message);
   }
   g.call("Hello, World");
-  self::caller(([dynamic x = #C1]) → core::Null* {
+  self::caller(([dynamic x = #C1]) → core::Null? {
     core::print("<anon> was called with ${x}");
   });
-  function h({dynamic message = #C1}) → core::Null* {
+  function h({dynamic message = #C1}) → core::Null? {
     core::print(message);
   }
   h.call(message: "Hello, World");
-  self::caller(({dynamic x = #C1}) → core::Null* {
+  self::caller(({dynamic x = #C1}) → core::Null? {
     core::print("<anon> was called with ${x}");
   });
   core::print(core::int*.{core::Object::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 741dfc4..d50717a 100644
--- a/pkg/front_end/testcases/general/expressions.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/expressions.dart.strong.transformed.expect
@@ -51,25 +51,25 @@
   core::print(#C2);
   core::print(core::_List::•<core::String*>(2).{core::Object::runtimeType});
   self::foo(fisk: "Blorp gulp");
-  function f() → core::Null* {
+  function f() → core::Null? {
     core::print("f was called");
   }
   self::caller(f);
-  self::caller(() → core::Null* {
+  self::caller(() → core::Null? {
     core::print("<anon> was called");
   });
-  function g([dynamic message = #C1]) → core::Null* {
+  function g([dynamic message = #C1]) → core::Null? {
     core::print(message);
   }
   g.call("Hello, World");
-  self::caller(([dynamic x = #C1]) → core::Null* {
+  self::caller(([dynamic x = #C1]) → core::Null? {
     core::print("<anon> was called with ${x}");
   });
-  function h({dynamic message = #C1}) → core::Null* {
+  function h({dynamic message = #C1}) → core::Null? {
     core::print(message);
   }
   h.call(message: "Hello, World");
-  self::caller(({dynamic x = #C1}) → core::Null* {
+  self::caller(({dynamic x = #C1}) → core::Null? {
     core::print("<anon> was called with ${x}");
   });
   core::print(core::int*.{core::Object::toString}());
diff --git a/pkg/front_end/testcases/general/function_type_is_check.dart.strong.expect b/pkg/front_end/testcases/general/function_type_is_check.dart.strong.expect
index 7493073..e3d7cfb 100644
--- a/pkg/front_end/testcases/general/function_type_is_check.dart.strong.expect
+++ b/pkg/front_end/testcases/general/function_type_is_check.dart.strong.expect
@@ -14,5 +14,5 @@
     return 100;
 }
 static method main() → dynamic {
-  exp::Expect::equals(111, self::test(() → core::Null* => null).+(self::test((core::Object* o) → core::Null* => null)).+(self::test((core::Object* o, core::StackTrace* t) → core::Null* => null)));
+  exp::Expect::equals(111, self::test(() → core::Null? => null).+(self::test((core::Object* o) → core::Null? => null)).+(self::test((core::Object* o, core::StackTrace* t) → core::Null? => null)));
 }
diff --git a/pkg/front_end/testcases/general/function_type_is_check.dart.strong.transformed.expect b/pkg/front_end/testcases/general/function_type_is_check.dart.strong.transformed.expect
index 7493073..e3d7cfb 100644
--- a/pkg/front_end/testcases/general/function_type_is_check.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/function_type_is_check.dart.strong.transformed.expect
@@ -14,5 +14,5 @@
     return 100;
 }
 static method main() → dynamic {
-  exp::Expect::equals(111, self::test(() → core::Null* => null).+(self::test((core::Object* o) → core::Null* => null)).+(self::test((core::Object* o, core::StackTrace* t) → core::Null* => null)));
+  exp::Expect::equals(111, self::test(() → core::Null? => null).+(self::test((core::Object* o) → core::Null? => null)).+(self::test((core::Object* o, core::StackTrace* t) → core::Null? => null)));
 }
diff --git a/pkg/front_end/testcases/general/functions.dart.strong.expect b/pkg/front_end/testcases/general/functions.dart.strong.expect
index 7b58e1b..f6f35ca 100644
--- a/pkg/front_end/testcases/general/functions.dart.strong.expect
+++ b/pkg/front_end/testcases/general/functions.dart.strong.expect
@@ -7,7 +7,7 @@
     f.call(a: "Hello, World");
     f.call();
   }
-  local.call(({dynamic a = #C1}) → core::Null* {
+  local.call(({dynamic a = #C1}) → core::Null? {
     core::print(a);
   });
 }
diff --git a/pkg/front_end/testcases/general/functions.dart.strong.transformed.expect b/pkg/front_end/testcases/general/functions.dart.strong.transformed.expect
index 7b58e1b..f6f35ca 100644
--- a/pkg/front_end/testcases/general/functions.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/functions.dart.strong.transformed.expect
@@ -7,7 +7,7 @@
     f.call(a: "Hello, World");
     f.call();
   }
-  local.call(({dynamic a = #C1}) → core::Null* {
+  local.call(({dynamic a = #C1}) → core::Null? {
     core::print(a);
   });
 }
diff --git a/pkg/front_end/testcases/general/illegal_named_function_expression.dart.strong.expect b/pkg/front_end/testcases/general/illegal_named_function_expression.dart.strong.expect
index 71eaf54..9284232 100644
--- a/pkg/front_end/testcases/general/illegal_named_function_expression.dart.strong.expect
+++ b/pkg/front_end/testcases/general/illegal_named_function_expression.dart.strong.expect
@@ -14,7 +14,7 @@
 import "dart:core" as core;
 
 static method main() → dynamic {
-  <T extends core::Object* = dynamic>(T*) →* core::Null* x = let final <T extends core::Object* = dynamic>(T*) →* core::Null* f = <T extends core::Object* = dynamic>(T* t) → core::Null* {} in f;
+  <T extends core::Object* = dynamic>(T*) →* core::Null? x = let final <T extends core::Object* = dynamic>(T*) →* core::Null? f = <T extends core::Object* = dynamic>(T* t) → core::Null? {} in f;
   core::print(x.{core::Object::runtimeType});
-  core::print(let final <T extends core::Object* = dynamic>(T*) →* core::Null* g = <T extends core::Object* = dynamic>(T* t) → core::Null* {} in g);
+  core::print(let final <T extends core::Object* = dynamic>(T*) →* core::Null? g = <T extends core::Object* = dynamic>(T* t) → core::Null? {} in g);
 }
diff --git a/pkg/front_end/testcases/general/illegal_named_function_expression.dart.strong.transformed.expect b/pkg/front_end/testcases/general/illegal_named_function_expression.dart.strong.transformed.expect
index 71eaf54..9284232 100644
--- a/pkg/front_end/testcases/general/illegal_named_function_expression.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/illegal_named_function_expression.dart.strong.transformed.expect
@@ -14,7 +14,7 @@
 import "dart:core" as core;
 
 static method main() → dynamic {
-  <T extends core::Object* = dynamic>(T*) →* core::Null* x = let final <T extends core::Object* = dynamic>(T*) →* core::Null* f = <T extends core::Object* = dynamic>(T* t) → core::Null* {} in f;
+  <T extends core::Object* = dynamic>(T*) →* core::Null? x = let final <T extends core::Object* = dynamic>(T*) →* core::Null? f = <T extends core::Object* = dynamic>(T* t) → core::Null? {} in f;
   core::print(x.{core::Object::runtimeType});
-  core::print(let final <T extends core::Object* = dynamic>(T*) →* core::Null* g = <T extends core::Object* = dynamic>(T* t) → core::Null* {} in g);
+  core::print(let final <T extends core::Object* = dynamic>(T*) →* core::Null? g = <T extends core::Object* = dynamic>(T* t) → core::Null? {} in g);
 }
diff --git a/pkg/front_end/testcases/general/illegal_named_function_expression_scope.dart.strong.expect b/pkg/front_end/testcases/general/illegal_named_function_expression_scope.dart.strong.expect
index da7462d..ad827f9 100644
--- a/pkg/front_end/testcases/general/illegal_named_function_expression_scope.dart.strong.expect
+++ b/pkg/front_end/testcases/general/illegal_named_function_expression_scope.dart.strong.expect
@@ -11,5 +11,5 @@
 
 static method main() → dynamic {
   function f() → void {}
-  core::print(let final () →* core::Null* f = () → core::Null* {} in f);
+  core::print(let final () →* core::Null? f = () → core::Null? {} in f);
 }
diff --git a/pkg/front_end/testcases/general/illegal_named_function_expression_scope.dart.strong.transformed.expect b/pkg/front_end/testcases/general/illegal_named_function_expression_scope.dart.strong.transformed.expect
index da7462d..ad827f9 100644
--- a/pkg/front_end/testcases/general/illegal_named_function_expression_scope.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/illegal_named_function_expression_scope.dart.strong.transformed.expect
@@ -11,5 +11,5 @@
 
 static method main() → dynamic {
   function f() → void {}
-  core::print(let final () →* core::Null* f = () → core::Null* {} in f);
+  core::print(let final () →* core::Null? f = () → core::Null? {} in f);
 }
diff --git a/pkg/front_end/testcases/general/magic_const.dart.strong.expect b/pkg/front_end/testcases/general/magic_const.dart.strong.expect
index 6d9ece4..de74647 100644
--- a/pkg/front_end/testcases/general/magic_const.dart.strong.expect
+++ b/pkg/front_end/testcases/general/magic_const.dart.strong.expect
@@ -15,6 +15,21 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/general/magic_const.dart:15:9: Error: Constant expression expected.
+// Try inserting 'const'.
+// foo({a: Constant(), b: Constant(), c: []}) {}
+//         ^^^^^^^^
+//
+// pkg/front_end/testcases/general/magic_const.dart:15:24: Error: Constant expression expected.
+// Try inserting 'const'.
+// foo({a: Constant(), b: Constant(), c: []}) {}
+//                        ^^^^^^^^
+//
+// pkg/front_end/testcases/general/magic_const.dart:15:39: Error: Constant expression expected.
+// Try inserting 'const'.
+// foo({a: Constant(), b: Constant(), c: []}) {}
+//                                       ^
+//
 // pkg/front_end/testcases/general/magic_const.dart:18:9: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
 // Try using a constructor or factory that is 'const'.
 //   const NotConstant();
diff --git a/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect b/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect
index 6d9ece4..de74647 100644
--- a/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect
@@ -15,6 +15,21 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/general/magic_const.dart:15:9: Error: Constant expression expected.
+// Try inserting 'const'.
+// foo({a: Constant(), b: Constant(), c: []}) {}
+//         ^^^^^^^^
+//
+// pkg/front_end/testcases/general/magic_const.dart:15:24: Error: Constant expression expected.
+// Try inserting 'const'.
+// foo({a: Constant(), b: Constant(), c: []}) {}
+//                        ^^^^^^^^
+//
+// pkg/front_end/testcases/general/magic_const.dart:15:39: Error: Constant expression expected.
+// Try inserting 'const'.
+// foo({a: Constant(), b: Constant(), c: []}) {}
+//                                       ^
+//
 // pkg/front_end/testcases/general/magic_const.dart:18:9: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
 // Try using a constructor or factory that is 'const'.
 //   const NotConstant();
diff --git a/pkg/front_end/testcases/general/named_function_scope.dart.strong.expect b/pkg/front_end/testcases/general/named_function_scope.dart.strong.expect
index 982626e..d13b4f3 100644
--- a/pkg/front_end/testcases/general/named_function_scope.dart.strong.expect
+++ b/pkg/front_end/testcases/general/named_function_scope.dart.strong.expect
@@ -98,14 +98,14 @@
   self::T* t;
   self::V* v;
   {
-    function T() → core::Null* {}
+    function T() → core::Null? {}
   }
   {
     dynamic v;
   }
   {
     self::T* t;
-    () →* core::Null* x = let final () →* core::Null* T = () → core::Null* {} in T;
+    () →* core::Null? x = let final () →* core::Null? T = () → core::Null? {} in T;
   }
   {
     self::V* v;
diff --git a/pkg/front_end/testcases/general/named_function_scope.dart.strong.transformed.expect b/pkg/front_end/testcases/general/named_function_scope.dart.strong.transformed.expect
index 982626e..d13b4f3 100644
--- a/pkg/front_end/testcases/general/named_function_scope.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/named_function_scope.dart.strong.transformed.expect
@@ -98,14 +98,14 @@
   self::T* t;
   self::V* v;
   {
-    function T() → core::Null* {}
+    function T() → core::Null? {}
   }
   {
     dynamic v;
   }
   {
     self::T* t;
-    () →* core::Null* x = let final () →* core::Null* T = () → core::Null* {} in T;
+    () →* core::Null? x = let final () →* core::Null? T = () → core::Null? {} in T;
   }
   {
     self::V* v;
diff --git a/pkg/front_end/testcases/general/nested_property_set.dart b/pkg/front_end/testcases/general/nested_property_set.dart
new file mode 100644
index 0000000..6b12100
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_property_set.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.
+
+class NumField {
+  num field;
+}
+
+class IntField {
+  int field;
+}
+
+class DoubleField {
+  double field;
+}
+
+main() {
+  IntField intField1 = new IntField();
+  IntField intField2 = new IntField();
+  NumField numField = new NumField();
+  DoubleField doubleField = new DoubleField();
+
+  intField1.field = intField2.field = numField.field;
+  intField1.field = numField.field = intField2.field;
+  try {
+    numField.field = 0.5;
+    intField1.field = doubleField.field = numField.field;
+    throw 'Should fail';
+  } catch (_) {}
+}
diff --git a/pkg/front_end/testcases/general/nested_property_set.dart.outline.expect b/pkg/front_end/testcases/general/nested_property_set.dart.outline.expect
new file mode 100644
index 0000000..3417b90
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_property_set.dart.outline.expect
@@ -0,0 +1,21 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class NumField extends core::Object {
+  field core::num* field;
+  synthetic constructor •() → self::NumField*
+    ;
+}
+class IntField extends core::Object {
+  field core::int* field;
+  synthetic constructor •() → self::IntField*
+    ;
+}
+class DoubleField extends core::Object {
+  field core::double* field;
+  synthetic constructor •() → self::DoubleField*
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/nested_property_set.dart.strong.expect b/pkg/front_end/testcases/general/nested_property_set.dart.strong.expect
new file mode 100644
index 0000000..1660b62
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_property_set.dart.strong.expect
@@ -0,0 +1,37 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class NumField extends core::Object {
+  field core::num* field = null;
+  synthetic constructor •() → self::NumField*
+    : super core::Object::•()
+    ;
+}
+class IntField extends core::Object {
+  field core::int* field = null;
+  synthetic constructor •() → self::IntField*
+    : super core::Object::•()
+    ;
+}
+class DoubleField extends core::Object {
+  field core::double* field = null;
+  synthetic constructor •() → self::DoubleField*
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  self::IntField* intField1 = new self::IntField::•();
+  self::IntField* intField2 = new self::IntField::•();
+  self::NumField* numField = new self::NumField::•();
+  self::DoubleField* doubleField = new self::DoubleField::•();
+  intField1.{self::IntField::field} = (intField2.{self::IntField::field} = numField.{self::NumField::field} as{TypeError} core::int*) as{TypeError} core::int*;
+  intField1.{self::IntField::field} = numField.{self::NumField::field} = intField2.{self::IntField::field};
+  try {
+    numField.{self::NumField::field} = 0.5;
+    intField1.{self::IntField::field} = (doubleField.{self::DoubleField::field} = numField.{self::NumField::field} as{TypeError} core::double*) as{TypeError} core::int*;
+    throw "Should fail";
+  }
+  on dynamic catch(final dynamic _) {
+  }
+}
diff --git a/pkg/front_end/testcases/general/nested_property_set.dart.strong.transformed.expect b/pkg/front_end/testcases/general/nested_property_set.dart.strong.transformed.expect
new file mode 100644
index 0000000..1660b62
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_property_set.dart.strong.transformed.expect
@@ -0,0 +1,37 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class NumField extends core::Object {
+  field core::num* field = null;
+  synthetic constructor •() → self::NumField*
+    : super core::Object::•()
+    ;
+}
+class IntField extends core::Object {
+  field core::int* field = null;
+  synthetic constructor •() → self::IntField*
+    : super core::Object::•()
+    ;
+}
+class DoubleField extends core::Object {
+  field core::double* field = null;
+  synthetic constructor •() → self::DoubleField*
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  self::IntField* intField1 = new self::IntField::•();
+  self::IntField* intField2 = new self::IntField::•();
+  self::NumField* numField = new self::NumField::•();
+  self::DoubleField* doubleField = new self::DoubleField::•();
+  intField1.{self::IntField::field} = (intField2.{self::IntField::field} = numField.{self::NumField::field} as{TypeError} core::int*) as{TypeError} core::int*;
+  intField1.{self::IntField::field} = numField.{self::NumField::field} = intField2.{self::IntField::field};
+  try {
+    numField.{self::NumField::field} = 0.5;
+    intField1.{self::IntField::field} = (doubleField.{self::DoubleField::field} = numField.{self::NumField::field} as{TypeError} core::double*) as{TypeError} core::int*;
+    throw "Should fail";
+  }
+  on dynamic catch(final dynamic _) {
+  }
+}
diff --git a/pkg/front_end/testcases/general/nested_variable_set.dart b/pkg/front_end/testcases/general/nested_variable_set.dart
new file mode 100644
index 0000000..4babd49
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_variable_set.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.
+
+main() {
+  int intLocal1;
+  int intLocal2;
+  num numLocal;
+  double doubleLocal;
+
+  intLocal1 = intLocal2 = numLocal;
+  intLocal1 = numLocal = intLocal2;
+  numLocal = 0.5;
+  try {
+    intLocal1 = doubleLocal = numLocal;
+    throw 'Should fail';
+  } catch (_) {}
+}
diff --git a/pkg/front_end/testcases/general/nested_variable_set.dart.outline.expect b/pkg/front_end/testcases/general/nested_variable_set.dart.outline.expect
new file mode 100644
index 0000000..6a28c0d
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_variable_set.dart.outline.expect
@@ -0,0 +1,5 @@
+library;
+import self as self;
+
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/nested_variable_set.dart.strong.expect b/pkg/front_end/testcases/general/nested_variable_set.dart.strong.expect
new file mode 100644
index 0000000..7e193c1
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_variable_set.dart.strong.expect
@@ -0,0 +1,19 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::int* intLocal1;
+  core::int* intLocal2;
+  core::num* numLocal;
+  core::double* doubleLocal;
+  intLocal1 = (intLocal2 = numLocal as{TypeError} core::int*) as{TypeError} core::int*;
+  intLocal1 = numLocal = intLocal2;
+  numLocal = 0.5;
+  try {
+    intLocal1 = (doubleLocal = numLocal as{TypeError} core::double*) as{TypeError} core::int*;
+    throw "Should fail";
+  }
+  on dynamic catch(final dynamic _) {
+  }
+}
diff --git a/pkg/front_end/testcases/general/nested_variable_set.dart.strong.transformed.expect b/pkg/front_end/testcases/general/nested_variable_set.dart.strong.transformed.expect
new file mode 100644
index 0000000..7e193c1
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_variable_set.dart.strong.transformed.expect
@@ -0,0 +1,19 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::int* intLocal1;
+  core::int* intLocal2;
+  core::num* numLocal;
+  core::double* doubleLocal;
+  intLocal1 = (intLocal2 = numLocal as{TypeError} core::int*) as{TypeError} core::int*;
+  intLocal1 = numLocal = intLocal2;
+  numLocal = 0.5;
+  try {
+    intLocal1 = (doubleLocal = numLocal as{TypeError} core::double*) as{TypeError} core::int*;
+    throw "Should fail";
+  }
+  on dynamic catch(final dynamic _) {
+  }
+}
diff --git a/pkg/front_end/testcases/general/nested_variable_set.dart.type_promotion.expect b/pkg/front_end/testcases/general/nested_variable_set.dart.type_promotion.expect
new file mode 100644
index 0000000..6aa997e
--- /dev/null
+++ b/pkg/front_end/testcases/general/nested_variable_set.dart.type_promotion.expect
@@ -0,0 +1,21 @@
+pkg/front_end/testcases/general/nested_variable_set.dart:11:25: Context: Write to intLocal2@249
+  intLocal1 = intLocal2 = numLocal;
+                        ^
+pkg/front_end/testcases/general/nested_variable_set.dart:11:13: Context: Write to intLocal1@232
+  intLocal1 = intLocal2 = numLocal;
+            ^
+pkg/front_end/testcases/general/nested_variable_set.dart:12:24: Context: Write to numLocal@266
+  intLocal1 = numLocal = intLocal2;
+                       ^
+pkg/front_end/testcases/general/nested_variable_set.dart:12:13: Context: Write to intLocal1@232
+  intLocal1 = numLocal = intLocal2;
+            ^
+pkg/front_end/testcases/general/nested_variable_set.dart:13:12: Context: Write to numLocal@266
+  numLocal = 0.5;
+           ^
+pkg/front_end/testcases/general/nested_variable_set.dart:15:29: Context: Write to doubleLocal@285
+    intLocal1 = doubleLocal = numLocal;
+                            ^
+pkg/front_end/testcases/general/nested_variable_set.dart:15:15: Context: Write to intLocal1@232
+    intLocal1 = doubleLocal = numLocal;
+              ^
diff --git a/pkg/front_end/testcases/general/non_covariant_checks.dart.strong.expect b/pkg/front_end/testcases/general/non_covariant_checks.dart.strong.expect
index 0b3bcfc..17ac3e7 100644
--- a/pkg/front_end/testcases/general/non_covariant_checks.dart.strong.expect
+++ b/pkg/front_end/testcases/general/non_covariant_checks.dart.strong.expect
@@ -19,7 +19,7 @@
   generic-covariant-impl field <S extends self::C::T* = dynamic>(S*) →* S* field14;
   generic-covariant-impl field (<S extends self::C::T* = dynamic>() →* S*) →* void field15;
   constructor •(self::C::T* field1) → self::C<self::C::T*>*
-    : self::C::field1 = field1, self::C::field2 = () → self::C::T* => field1, self::C::field3 = (self::C::T* t) → core::Null* {}, self::C::field4 = (self::C::T* t) → self::C::T* => t, self::C::field5 = () → () →* self::C::T* => () → self::C::T* => field1, self::C::field6 = (() →* self::C::T* f) → core::Null* {}, self::C::field7 = (() →* self::C::T* f) → self::C::T* => field1, self::C::field8 = ((self::C::T*) →* void f) → core::Null* {}, self::C::field9 = ((self::C::T*) →* void f) → self::C::T* => field1, self::C::field10 = ((self::C::T*) →* self::C::T* f) → core::Null* {}, self::C::field11 = ((self::C::T*) →* self::C::T* f) → self::C::T* => field1, self::C::field12 = <S extends self::C::T* = self::C::T*>() → core::Null* => null, self::C::field13 = <S extends self::C::T* = self::C::T*>(S* s) → core::Null* {}, self::C::field14 = <S extends self::C::T* = self::C::T*>(S* s) → S* => s, self::C::field15 = (<S extends self::C::T* = self::C::T*>() →* S* f) → core::Null* {}, super core::Object::•()
+    : self::C::field1 = field1, self::C::field2 = () → self::C::T* => field1, self::C::field3 = (self::C::T* t) → core::Null? {}, self::C::field4 = (self::C::T* t) → self::C::T* => t, self::C::field5 = () → () →* self::C::T* => () → self::C::T* => field1, self::C::field6 = (() →* self::C::T* f) → core::Null? {}, self::C::field7 = (() →* self::C::T* f) → self::C::T* => field1, self::C::field8 = ((self::C::T*) →* void f) → core::Null? {}, self::C::field9 = ((self::C::T*) →* void f) → self::C::T* => field1, self::C::field10 = ((self::C::T*) →* self::C::T* f) → core::Null? {}, self::C::field11 = ((self::C::T*) →* self::C::T* f) → self::C::T* => field1, self::C::field12 = <S extends self::C::T* = self::C::T*>() → core::Null? => null, self::C::field13 = <S extends self::C::T* = self::C::T*>(S* s) → core::Null? {}, self::C::field14 = <S extends self::C::T* = self::C::T*>(S* s) → S* => s, self::C::field15 = (<S extends self::C::T* = self::C::T*>() →* S* f) → core::Null? {}, super core::Object::•()
     ;
   get getter1() → self::C::T*
     return this.{self::C::field1};
@@ -308,7 +308,7 @@
   on core::TypeError* catch(final core::TypeError* e) {
     core::print(e);
   }
-  c.{self::C::setter3} = (core::num* n) → core::Null* {};
+  c.{self::C::setter3} = (core::num* n) → core::Null? {};
   try {
     c.{self::C::setter4} = (core::num* n) → core::double* => 0.5;
     throw "TypeError expected";
@@ -323,7 +323,7 @@
   on core::TypeError* catch(final core::TypeError* e) {
     core::print(e);
   }
-  c.{self::C::setter6} = (() →* core::num* f) → core::Null* {};
+  c.{self::C::setter6} = (() →* core::num* f) → core::Null? {};
   try {
     c.{self::C::setter7} = (() →* core::num* f) → core::double* => 0.5;
     throw "TypeError expected";
@@ -332,7 +332,7 @@
     core::print(e);
   }
   try {
-    c.{self::C::setter8} = ((core::double*) →* void f) → core::Null* {};
+    c.{self::C::setter8} = ((core::double*) →* void f) → core::Null? {};
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
@@ -346,7 +346,7 @@
     core::print(e);
   }
   try {
-    c.{self::C::setter10} = ((core::double*) →* core::num* f) → core::Null* {};
+    c.{self::C::setter10} = ((core::double*) →* core::num* f) → core::Null? {};
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
@@ -360,14 +360,14 @@
     core::print(e);
   }
   try {
-    c.{self::C::setter12} = <S extends core::num* = core::num*>() → core::Null* => null;
+    c.{self::C::setter12} = <S extends core::num* = core::num*>() → core::Null? => null;
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
     core::print(e);
   }
   try {
-    c.{self::C::setter13} = <S extends core::num* = core::num*>(S* s) → core::Null* {};
+    c.{self::C::setter13} = <S extends core::num* = core::num*>(S* s) → core::Null? {};
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
@@ -381,7 +381,7 @@
     core::print(e);
   }
   try {
-    c.{self::C::setter15} = (<S extends core::num* = core::num*>() →* S* f) → core::Null* {};
+    c.{self::C::setter15} = (<S extends core::num* = core::num*>() →* S* f) → core::Null? {};
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
@@ -401,7 +401,7 @@
   on core::TypeError* catch(final core::TypeError* e) {
     core::print(e);
   }
-  c.{self::C::method3}((core::num* n) → core::Null* {});
+  c.{self::C::method3}((core::num* n) → core::Null? {});
   try {
     c.{self::C::method4}((core::num* n) → core::double* => 0.5);
     throw "TypeError expected";
@@ -416,7 +416,7 @@
   on core::TypeError* catch(final core::TypeError* e) {
     core::print(e);
   }
-  c.{self::C::method6}((() →* core::num* f) → core::Null* {});
+  c.{self::C::method6}((() →* core::num* f) → core::Null? {});
   try {
     c.{self::C::method7}((() →* core::num* f) → core::double* => 0.5);
     throw "TypeError expected";
@@ -425,7 +425,7 @@
     core::print(e);
   }
   try {
-    c.{self::C::method8}(((core::double*) →* void f) → core::Null* {});
+    c.{self::C::method8}(((core::double*) →* void f) → core::Null? {});
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
@@ -439,7 +439,7 @@
     core::print(e);
   }
   try {
-    c.{self::C::method10}(((core::double*) →* core::num* f) → core::Null* {});
+    c.{self::C::method10}(((core::double*) →* core::num* f) → core::Null? {});
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
@@ -453,14 +453,14 @@
     core::print(e);
   }
   try {
-    c.{self::C::method12}(<S extends core::num* = core::num*>() → core::Null* => null);
+    c.{self::C::method12}(<S extends core::num* = core::num*>() → core::Null? => null);
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
     core::print(e);
   }
   try {
-    c.{self::C::method13}(<S extends core::num* = core::num*>(S* s) → core::Null* {});
+    c.{self::C::method13}(<S extends core::num* = core::num*>(S* s) → core::Null? {});
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
@@ -474,7 +474,7 @@
     core::print(e);
   }
   try {
-    c.{self::C::method15}((<S extends core::num* = core::num*>() →* S* f) → core::Null* {});
+    c.{self::C::method15}((<S extends core::num* = core::num*>() →* S* f) → core::Null? {});
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
diff --git a/pkg/front_end/testcases/general/non_covariant_checks.dart.strong.transformed.expect b/pkg/front_end/testcases/general/non_covariant_checks.dart.strong.transformed.expect
index 0b3bcfc..17ac3e7 100644
--- a/pkg/front_end/testcases/general/non_covariant_checks.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/non_covariant_checks.dart.strong.transformed.expect
@@ -19,7 +19,7 @@
   generic-covariant-impl field <S extends self::C::T* = dynamic>(S*) →* S* field14;
   generic-covariant-impl field (<S extends self::C::T* = dynamic>() →* S*) →* void field15;
   constructor •(self::C::T* field1) → self::C<self::C::T*>*
-    : self::C::field1 = field1, self::C::field2 = () → self::C::T* => field1, self::C::field3 = (self::C::T* t) → core::Null* {}, self::C::field4 = (self::C::T* t) → self::C::T* => t, self::C::field5 = () → () →* self::C::T* => () → self::C::T* => field1, self::C::field6 = (() →* self::C::T* f) → core::Null* {}, self::C::field7 = (() →* self::C::T* f) → self::C::T* => field1, self::C::field8 = ((self::C::T*) →* void f) → core::Null* {}, self::C::field9 = ((self::C::T*) →* void f) → self::C::T* => field1, self::C::field10 = ((self::C::T*) →* self::C::T* f) → core::Null* {}, self::C::field11 = ((self::C::T*) →* self::C::T* f) → self::C::T* => field1, self::C::field12 = <S extends self::C::T* = self::C::T*>() → core::Null* => null, self::C::field13 = <S extends self::C::T* = self::C::T*>(S* s) → core::Null* {}, self::C::field14 = <S extends self::C::T* = self::C::T*>(S* s) → S* => s, self::C::field15 = (<S extends self::C::T* = self::C::T*>() →* S* f) → core::Null* {}, super core::Object::•()
+    : self::C::field1 = field1, self::C::field2 = () → self::C::T* => field1, self::C::field3 = (self::C::T* t) → core::Null? {}, self::C::field4 = (self::C::T* t) → self::C::T* => t, self::C::field5 = () → () →* self::C::T* => () → self::C::T* => field1, self::C::field6 = (() →* self::C::T* f) → core::Null? {}, self::C::field7 = (() →* self::C::T* f) → self::C::T* => field1, self::C::field8 = ((self::C::T*) →* void f) → core::Null? {}, self::C::field9 = ((self::C::T*) →* void f) → self::C::T* => field1, self::C::field10 = ((self::C::T*) →* self::C::T* f) → core::Null? {}, self::C::field11 = ((self::C::T*) →* self::C::T* f) → self::C::T* => field1, self::C::field12 = <S extends self::C::T* = self::C::T*>() → core::Null? => null, self::C::field13 = <S extends self::C::T* = self::C::T*>(S* s) → core::Null? {}, self::C::field14 = <S extends self::C::T* = self::C::T*>(S* s) → S* => s, self::C::field15 = (<S extends self::C::T* = self::C::T*>() →* S* f) → core::Null? {}, super core::Object::•()
     ;
   get getter1() → self::C::T*
     return this.{self::C::field1};
@@ -308,7 +308,7 @@
   on core::TypeError* catch(final core::TypeError* e) {
     core::print(e);
   }
-  c.{self::C::setter3} = (core::num* n) → core::Null* {};
+  c.{self::C::setter3} = (core::num* n) → core::Null? {};
   try {
     c.{self::C::setter4} = (core::num* n) → core::double* => 0.5;
     throw "TypeError expected";
@@ -323,7 +323,7 @@
   on core::TypeError* catch(final core::TypeError* e) {
     core::print(e);
   }
-  c.{self::C::setter6} = (() →* core::num* f) → core::Null* {};
+  c.{self::C::setter6} = (() →* core::num* f) → core::Null? {};
   try {
     c.{self::C::setter7} = (() →* core::num* f) → core::double* => 0.5;
     throw "TypeError expected";
@@ -332,7 +332,7 @@
     core::print(e);
   }
   try {
-    c.{self::C::setter8} = ((core::double*) →* void f) → core::Null* {};
+    c.{self::C::setter8} = ((core::double*) →* void f) → core::Null? {};
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
@@ -346,7 +346,7 @@
     core::print(e);
   }
   try {
-    c.{self::C::setter10} = ((core::double*) →* core::num* f) → core::Null* {};
+    c.{self::C::setter10} = ((core::double*) →* core::num* f) → core::Null? {};
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
@@ -360,14 +360,14 @@
     core::print(e);
   }
   try {
-    c.{self::C::setter12} = <S extends core::num* = core::num*>() → core::Null* => null;
+    c.{self::C::setter12} = <S extends core::num* = core::num*>() → core::Null? => null;
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
     core::print(e);
   }
   try {
-    c.{self::C::setter13} = <S extends core::num* = core::num*>(S* s) → core::Null* {};
+    c.{self::C::setter13} = <S extends core::num* = core::num*>(S* s) → core::Null? {};
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
@@ -381,7 +381,7 @@
     core::print(e);
   }
   try {
-    c.{self::C::setter15} = (<S extends core::num* = core::num*>() →* S* f) → core::Null* {};
+    c.{self::C::setter15} = (<S extends core::num* = core::num*>() →* S* f) → core::Null? {};
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
@@ -401,7 +401,7 @@
   on core::TypeError* catch(final core::TypeError* e) {
     core::print(e);
   }
-  c.{self::C::method3}((core::num* n) → core::Null* {});
+  c.{self::C::method3}((core::num* n) → core::Null? {});
   try {
     c.{self::C::method4}((core::num* n) → core::double* => 0.5);
     throw "TypeError expected";
@@ -416,7 +416,7 @@
   on core::TypeError* catch(final core::TypeError* e) {
     core::print(e);
   }
-  c.{self::C::method6}((() →* core::num* f) → core::Null* {});
+  c.{self::C::method6}((() →* core::num* f) → core::Null? {});
   try {
     c.{self::C::method7}((() →* core::num* f) → core::double* => 0.5);
     throw "TypeError expected";
@@ -425,7 +425,7 @@
     core::print(e);
   }
   try {
-    c.{self::C::method8}(((core::double*) →* void f) → core::Null* {});
+    c.{self::C::method8}(((core::double*) →* void f) → core::Null? {});
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
@@ -439,7 +439,7 @@
     core::print(e);
   }
   try {
-    c.{self::C::method10}(((core::double*) →* core::num* f) → core::Null* {});
+    c.{self::C::method10}(((core::double*) →* core::num* f) → core::Null? {});
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
@@ -453,14 +453,14 @@
     core::print(e);
   }
   try {
-    c.{self::C::method12}(<S extends core::num* = core::num*>() → core::Null* => null);
+    c.{self::C::method12}(<S extends core::num* = core::num*>() → core::Null? => null);
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
     core::print(e);
   }
   try {
-    c.{self::C::method13}(<S extends core::num* = core::num*>(S* s) → core::Null* {});
+    c.{self::C::method13}(<S extends core::num* = core::num*>(S* s) → core::Null? {});
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
@@ -474,7 +474,7 @@
     core::print(e);
   }
   try {
-    c.{self::C::method15}((<S extends core::num* = core::num*>() →* S* f) → core::Null* {});
+    c.{self::C::method15}((<S extends core::num* = core::num*>() →* S* f) → core::Null? {});
     throw "TypeError expected";
   }
   on core::TypeError* catch(final core::TypeError* e) {
diff --git a/pkg/front_end/testcases/general/null_aware.dart.strong.expect b/pkg/front_end/testcases/general/null_aware.dart.strong.expect
index 9cdabd6..8410392 100644
--- a/pkg/front_end/testcases/general/null_aware.dart.strong.expect
+++ b/pkg/front_end/testcases/general/null_aware.dart.strong.expect
@@ -11,7 +11,7 @@
 }
 static method main() → dynamic {
   self::Foo* foo = new self::Foo::•();
-  let final self::Foo* #t1 = foo in #t1.==(null) ?{core::int*} null : #t1.{self::Foo::field} = 5;
+  let final self::Foo* #t1 = foo in #t1.{core::Object::==}(null) ?{core::int*} null : #t1.{self::Foo::field} = 5;
   self::Foo::staticField = 5;
   let final self::Foo* #t2 = foo in #t2.{self::Foo::field}.{core::num::==}(null) ?{core::int*} #t2.{self::Foo::field} = 5 : null;
   self::Foo::staticField.{core::num::==}(null) ?{core::int*} self::Foo::staticField = 5 : null;
diff --git a/pkg/front_end/testcases/general/null_aware.dart.strong.transformed.expect b/pkg/front_end/testcases/general/null_aware.dart.strong.transformed.expect
index 9cdabd6..8410392 100644
--- a/pkg/front_end/testcases/general/null_aware.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/null_aware.dart.strong.transformed.expect
@@ -11,7 +11,7 @@
 }
 static method main() → dynamic {
   self::Foo* foo = new self::Foo::•();
-  let final self::Foo* #t1 = foo in #t1.==(null) ?{core::int*} null : #t1.{self::Foo::field} = 5;
+  let final self::Foo* #t1 = foo in #t1.{core::Object::==}(null) ?{core::int*} null : #t1.{self::Foo::field} = 5;
   self::Foo::staticField = 5;
   let final self::Foo* #t2 = foo in #t2.{self::Foo::field}.{core::num::==}(null) ?{core::int*} #t2.{self::Foo::field} = 5 : null;
   self::Foo::staticField.{core::num::==}(null) ?{core::int*} self::Foo::staticField = 5 : null;
diff --git a/runtime/lib/wasm_patch.dart b/pkg/front_end/testcases/general/null_aware_for_in.dart
similarity index 62%
rename from runtime/lib/wasm_patch.dart
rename to pkg/front_end/testcases/general/null_aware_for_in.dart
index 2af1b20..5a93b8e 100644
--- a/runtime/lib/wasm_patch.dart
+++ b/pkg/front_end/testcases/general/null_aware_for_in.dart
@@ -2,7 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import "dart:_internal" show patch;
+class Class {}
 
-@patch
-int _callWasm(String name, int arg) native "Wasm_callFunction";
+main() {
+  var o;
+  if (false) {
+    // ignore: unused_local_variable
+    for (Class c in o?.iterable) {}
+  }
+}
diff --git a/pkg/front_end/testcases/general/null_aware_for_in.dart.outline.expect b/pkg/front_end/testcases/general/null_aware_for_in.dart.outline.expect
new file mode 100644
index 0000000..b23757d
--- /dev/null
+++ b/pkg/front_end/testcases/general/null_aware_for_in.dart.outline.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/null_aware_for_in.dart.strong.expect b/pkg/front_end/testcases/general/null_aware_for_in.dart.strong.expect
new file mode 100644
index 0000000..18203ab
--- /dev/null
+++ b/pkg/front_end/testcases/general/null_aware_for_in.dart.strong.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  dynamic o;
+  if(false) {
+    for (final dynamic #t1 in (let final dynamic #t2 = o in #t2.{core::Object::==}(null) ?{dynamic} null : #t2.iterable) as{TypeError} core::Iterable<dynamic>*) {
+      self::Class* c = #t1 as{TypeError} self::Class*;
+    }
+  }
+}
diff --git a/pkg/front_end/testcases/general/null_aware_for_in.dart.strong.transformed.expect b/pkg/front_end/testcases/general/null_aware_for_in.dart.strong.transformed.expect
new file mode 100644
index 0000000..18203ab
--- /dev/null
+++ b/pkg/front_end/testcases/general/null_aware_for_in.dart.strong.transformed.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {
+  dynamic o;
+  if(false) {
+    for (final dynamic #t1 in (let final dynamic #t2 = o in #t2.{core::Object::==}(null) ?{dynamic} null : #t2.iterable) as{TypeError} core::Iterable<dynamic>*) {
+      self::Class* c = #t1 as{TypeError} self::Class*;
+    }
+  }
+}
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 4860020..8eafc0b 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
@@ -275,7 +275,7 @@
 Try correcting the name to the name of an existing method, or defining a method named '>>'.
   print(foo >> 2);
             ^^");
-  core::print(let final self::Foo* #t1 = foo in let final core::int* #t2 = 2 in let final core::int* #t3 = 2 in let final dynamic #t4 = invalid-expression "pkg/front_end/testcases/general/operator_method_not_found.dart:29:12: Error: The method '[]=' isn't defined for the class 'Foo'.
+  core::print(let final self::Foo* #t1 = foo in let final core::int* #t2 = 2 in let final core::int* #t3 = 2 in let final void #t4 = invalid-expression "pkg/front_end/testcases/general/operator_method_not_found.dart:29: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 '[]='.
   print(foo[2] = 2);
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 4860020..8eafc0b 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
@@ -275,7 +275,7 @@
 Try correcting the name to the name of an existing method, or defining a method named '>>'.
   print(foo >> 2);
             ^^");
-  core::print(let final self::Foo* #t1 = foo in let final core::int* #t2 = 2 in let final core::int* #t3 = 2 in let final dynamic #t4 = invalid-expression "pkg/front_end/testcases/general/operator_method_not_found.dart:29:12: Error: The method '[]=' isn't defined for the class 'Foo'.
+  core::print(let final self::Foo* #t1 = foo in let final core::int* #t2 = 2 in let final core::int* #t3 = 2 in let final void #t4 = invalid-expression "pkg/front_end/testcases/general/operator_method_not_found.dart:29: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 '[]='.
   print(foo[2] = 2);
diff --git a/pkg/front_end/testcases/general/qualified.dart.strong.transformed.expect b/pkg/front_end/testcases/general/qualified.dart.strong.transformed.expect
index 22e7c21..f45751f 100644
--- a/pkg/front_end/testcases/general/qualified.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/qualified.dart.strong.transformed.expect
@@ -59,7 +59,7 @@
     : super core::Object::•()
     ;
   static factory b<T extends core::Object* = dynamic>() → self::C<self::C::b::T*>*
-    let <T extends core::Object* = dynamic>() →* lib::C<lib::C::b::T*>* #redirecting_factory = lib::C::b in let self::C::b::T* #typeArg0 = null in invalid-expression;
+    let <T extends core::Object* = dynamic>() →* lib::C<T*>* #redirecting_factory = lib::C::b in let self::C::b::T* #typeArg0 = null in invalid-expression;
 }
 static method main() → dynamic {
   new self::C::•<core::String*>();
diff --git a/pkg/front_end/testcases/general/redirecting_factory.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirecting_factory.dart.strong.transformed.expect
index fca2b95..c9e154b 100644
--- a/pkg/front_end/testcases/general/redirecting_factory.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory.dart.strong.transformed.expect
@@ -15,7 +15,7 @@
   static field dynamic _redirecting# = <dynamic>[self::FooBase::•];
   abstract get x() → core::int*;
   static factory •<Tf extends core::Object* = dynamic>(core::int* x) → self::FooBase<self::FooBase::•::Tf*>*
-    let <T extends core::Object* = dynamic>(core::int*) →* self::Foo<self::Foo::•::T*>* #redirecting_factory = self::Foo::• in let self::FooBase::•::Tf* #typeArg0 = null in invalid-expression;
+    let <T extends core::Object* = dynamic>(core::int*) →* self::Foo<T*>* #redirecting_factory = self::Foo::• in let self::FooBase::•::Tf* #typeArg0 = null in invalid-expression;
 }
 abstract class Foo<T extends core::Object* = dynamic> extends core::Object implements self::FooBase<dynamic> {
   static field dynamic _redirecting# = <dynamic>[self::Foo::•];
@@ -40,7 +40,7 @@
 class SimpleCase<A extends core::Object* = dynamic, B extends core::Object* = dynamic> extends core::Object {
   static field dynamic _redirecting# = <dynamic>[self::SimpleCase::•];
   static factory •<A extends core::Object* = dynamic, B extends core::Object* = dynamic>() → self::SimpleCase<self::SimpleCase::•::A*, self::SimpleCase::•::B*>*
-    let <Ai extends core::Object* = dynamic, Bi extends core::Object* = dynamic>() →* self::SimpleCaseImpl<self::SimpleCaseImpl::•::Ai*, self::SimpleCaseImpl::•::Bi*>* #redirecting_factory = self::SimpleCaseImpl::• in let self::SimpleCase::•::A* #typeArg0 = null in let self::SimpleCase::•::B* #typeArg1 = null in invalid-expression;
+    let <Ai extends core::Object* = dynamic, Bi extends core::Object* = dynamic>() →* self::SimpleCaseImpl<Ai*, Bi*>* #redirecting_factory = self::SimpleCaseImpl::• in let self::SimpleCase::•::A* #typeArg0 = null in let self::SimpleCase::•::B* #typeArg1 = null in invalid-expression;
 }
 class SimpleCaseImpl<Ai extends core::Object* = dynamic, Bi extends core::Object* = dynamic> extends core::Object implements self::SimpleCase<self::SimpleCaseImpl::Ai*, self::SimpleCaseImpl::Bi*> {
   static field dynamic _redirecting# = <dynamic>[self::SimpleCaseImpl::•];
diff --git a/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.expect b/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.expect
index 45acdcc..5f63429 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.expect
@@ -31,5 +31,5 @@
 }
 
 constants  {
-  #C1 = self::_Y<core::Null*> {}
+  #C1 = self::_Y<core::Null?> {}
 }
diff --git a/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.transformed.expect
index c84f680..a352dae88 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.transformed.expect
@@ -31,5 +31,5 @@
 }
 
 constants  {
-  #C1 = self::_Y<core::Null*> {}
+  #C1 = self::_Y<core::Null?> {}
 }
diff --git a/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.strong.transformed.expect
index ce90e29..f3111be 100644
--- a/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.strong.transformed.expect
@@ -11,7 +11,7 @@
     : super core::Object::•()
     ;
   static factory •<T extends core::Object* = dynamic>() → self::A<self::A::•::T*>*
-    let <U extends core::Object* = dynamic, W extends core::Object* = dynamic>() →* self::B<self::B::•::U*, self::B::•::W*>* #redirecting_factory = self::B::• in let self::A::•::T* #typeArg0 = null in let core::num* #typeArg1 = null in invalid-expression;
+    let <U extends core::Object* = dynamic, W extends core::Object* = dynamic>() →* self::B<U*, W*>* #redirecting_factory = self::B::• in let self::A::•::T* #typeArg0 = null in let core::num* #typeArg1 = null in invalid-expression;
 }
 class B<U extends core::Object* = dynamic, W extends core::Object* = dynamic> extends self::A<self::B::U*> {
   static field dynamic _redirecting# = <dynamic>[self::B::•];
diff --git a/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.strong.transformed.expect
index 14e0fef..6aa25a9 100644
--- a/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.strong.transformed.expect
@@ -11,7 +11,7 @@
     : super core::Object::•()
     ;
   static factory •<T extends core::Object* = dynamic>() → self::A<self::A::•::T*>*
-    let <U extends core::Object* = dynamic, W extends core::Object* = dynamic>() →* self::B<self::B::•::U*, self::B::•::W*>* #redirecting_factory = self::B::• in let self::A::•::T* #typeArg0 = null in let core::List<self::A::•::T*>* #typeArg1 = null in invalid-expression;
+    let <U extends core::Object* = dynamic, W extends core::Object* = dynamic>() →* self::B<U*, W*>* #redirecting_factory = self::B::• in let self::A::•::T* #typeArg0 = null in let core::List<self::A::•::T*>* #typeArg1 = null in invalid-expression;
 }
 abstract class B<U extends core::Object* = dynamic, W extends core::Object* = dynamic> extends self::A<self::B::U*> {
   static field dynamic _redirecting# = <dynamic>[self::B::•];
diff --git a/pkg/front_end/testcases/general/type_of_null.dart b/pkg/front_end/testcases/general/type_of_null.dart
index 0f7004e..39db639 100644
--- a/pkg/front_end/testcases/general/type_of_null.dart
+++ b/pkg/front_end/testcases/general/type_of_null.dart
@@ -10,22 +10,22 @@
 Null foo() => null;
 
 main() {
-  /*@ typeArgs=Null* */ map(/*@ returnType=Null* */ () {},
+  /*@ typeArgs=Null? */ map(/*@ returnType=Null? */ () {},
       /*@ returnType=<BottomType> */ () => throw "hello");
-  /*@ typeArgs=Null* */ map(/*@ returnType=<BottomType> */ () => throw "hello",
-      /*@ returnType=Null* */ () {});
-  Null Function() f = /*@ returnType=Null* */ () {};
+  /*@ typeArgs=Null? */ map(/*@ returnType=<BottomType> */ () => throw "hello",
+      /*@ returnType=Null? */ () {});
+  Null Function() f = /*@ returnType=Null? */ () {};
   /*@ typeArgs=Null* */ map(
       foo, /*@ returnType=<BottomType> */ () => throw "hello");
   /*@ typeArgs=Null* */ map(
       /*@ returnType=<BottomType> */ () => throw "hello", foo);
-  /*@ typeArgs=Null* */ map(/*@ returnType=Null* */ () {
+  /*@ typeArgs=Null? */ map(/*@ returnType=Null? */ () {
     return null;
   }, /*@ returnType=<BottomType> */ () => throw "hello");
 
-  /*@ typeArgs=Null* */ map(/*@ returnType=<BottomType> */ () => throw "hello",
-      /*@ returnType=Null* */ () {
+  /*@ typeArgs=Null? */ map(/*@ returnType=<BottomType> */ () => throw "hello",
+      /*@ returnType=Null? */ () {
     return null;
   });
-  /*@ typeArgs=() ->* Null* */ id(/*@ returnType=Null* */ () {});
+  /*@ typeArgs=() ->* Null? */ id(/*@ returnType=Null? */ () {});
 }
diff --git a/pkg/front_end/testcases/general/type_of_null.dart.strong.expect b/pkg/front_end/testcases/general/type_of_null.dart.strong.expect
index 0a6f445..40a4bed 100644
--- a/pkg/front_end/testcases/general/type_of_null.dart.strong.expect
+++ b/pkg/front_end/testcases/general/type_of_null.dart.strong.expect
@@ -8,18 +8,18 @@
 static method foo() → core::Null*
   return null;
 static method main() → dynamic {
-  self::map<core::Null*>(() → core::Null* {}, () → <BottomType>=> throw "hello");
-  self::map<core::Null*>(() → <BottomType>=> throw "hello", () → core::Null* {});
-  () →* core::Null* f = () → core::Null* {};
+  self::map<core::Null?>(() → core::Null? {}, () → <BottomType>=> throw "hello");
+  self::map<core::Null?>(() → <BottomType>=> throw "hello", () → core::Null? {});
+  () →* core::Null* f = () → core::Null? {};
   self::map<core::Null*>(#C1, () → <BottomType>=> throw "hello");
   self::map<core::Null*>(() → <BottomType>=> throw "hello", #C1);
-  self::map<core::Null*>(() → core::Null* {
+  self::map<core::Null?>(() → core::Null? {
     return null;
   }, () → <BottomType>=> throw "hello");
-  self::map<core::Null*>(() → <BottomType>=> throw "hello", () → core::Null* {
+  self::map<core::Null?>(() → <BottomType>=> throw "hello", () → core::Null? {
     return null;
   });
-  self::id<() →* core::Null*>(() → core::Null* {});
+  self::id<() →* core::Null?>(() → core::Null? {});
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/general/type_of_null.dart.strong.transformed.expect b/pkg/front_end/testcases/general/type_of_null.dart.strong.transformed.expect
index 0a6f445..40a4bed 100644
--- a/pkg/front_end/testcases/general/type_of_null.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/type_of_null.dart.strong.transformed.expect
@@ -8,18 +8,18 @@
 static method foo() → core::Null*
   return null;
 static method main() → dynamic {
-  self::map<core::Null*>(() → core::Null* {}, () → <BottomType>=> throw "hello");
-  self::map<core::Null*>(() → <BottomType>=> throw "hello", () → core::Null* {});
-  () →* core::Null* f = () → core::Null* {};
+  self::map<core::Null?>(() → core::Null? {}, () → <BottomType>=> throw "hello");
+  self::map<core::Null?>(() → <BottomType>=> throw "hello", () → core::Null? {});
+  () →* core::Null* f = () → core::Null? {};
   self::map<core::Null*>(#C1, () → <BottomType>=> throw "hello");
   self::map<core::Null*>(() → <BottomType>=> throw "hello", #C1);
-  self::map<core::Null*>(() → core::Null* {
+  self::map<core::Null?>(() → core::Null? {
     return null;
   }, () → <BottomType>=> throw "hello");
-  self::map<core::Null*>(() → <BottomType>=> throw "hello", () → core::Null* {
+  self::map<core::Null?>(() → <BottomType>=> throw "hello", () → core::Null? {
     return null;
   });
-  self::id<() →* core::Null*>(() → core::Null* {});
+  self::id<() →* core::Null?>(() → core::Null? {});
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/general/type_variable_bound_access.dart b/pkg/front_end/testcases/general/type_variable_bound_access.dart
new file mode 100644
index 0000000..720e493
--- /dev/null
+++ b/pkg/front_end/testcases/general/type_variable_bound_access.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.
+
+class DynamicClass<T extends dynamic, S extends T> {
+  T field1;
+  T field2;
+
+  DynamicClass(this.field1, this.field2);
+
+  method() => field1 * field2;
+}
+
+class NumClass<T extends num, S extends T> {
+  T field1;
+  S field2;
+
+  NumClass(this.field1, this.field2);
+
+  num method1() => field1 * field2;
+
+  num method2() => field1 + field2.length;
+}
+
+main() {
+  new DynamicClass<num, int>(0.5, 2).method();
+  new NumClass<num, double>(2, 0.5).method1();
+}
diff --git a/pkg/front_end/testcases/general/type_variable_bound_access.dart.outline.expect b/pkg/front_end/testcases/general/type_variable_bound_access.dart.outline.expect
new file mode 100644
index 0000000..11781a4
--- /dev/null
+++ b/pkg/front_end/testcases/general/type_variable_bound_access.dart.outline.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class DynamicClass<T extends dynamic = dynamic, S extends self::DynamicClass::T* = dynamic> extends core::Object {
+  generic-covariant-impl field self::DynamicClass::T* field1;
+  generic-covariant-impl field self::DynamicClass::T* field2;
+  constructor •(self::DynamicClass::T* field1, self::DynamicClass::T* field2) → self::DynamicClass<self::DynamicClass::T*, self::DynamicClass::S*>*
+    ;
+  method method() → dynamic
+    ;
+}
+class NumClass<T extends core::num* = core::num*, S extends self::NumClass::T* = core::num*> extends core::Object {
+  generic-covariant-impl field self::NumClass::T* field1;
+  generic-covariant-impl field self::NumClass::S* field2;
+  constructor •(self::NumClass::T* field1, self::NumClass::S* field2) → self::NumClass<self::NumClass::T*, self::NumClass::S*>*
+    ;
+  method method1() → core::num*
+    ;
+  method method2() → core::num*
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/type_variable_bound_access.dart.strong.expect b/pkg/front_end/testcases/general/type_variable_bound_access.dart.strong.expect
new file mode 100644
index 0000000..79514a6
--- /dev/null
+++ b/pkg/front_end/testcases/general/type_variable_bound_access.dart.strong.expect
@@ -0,0 +1,39 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/type_variable_bound_access.dart:22:36: Error: The getter 'length' isn't defined for the class 'num'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'length'.
+//   num method2() => field1 + field2.length;
+//                                    ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class DynamicClass<T extends dynamic = dynamic, S extends self::DynamicClass::T* = dynamic> extends core::Object {
+  generic-covariant-impl field self::DynamicClass::T* field1;
+  generic-covariant-impl field self::DynamicClass::T* field2;
+  constructor •(self::DynamicClass::T* field1, self::DynamicClass::T* field2) → self::DynamicClass<self::DynamicClass::T*, self::DynamicClass::S*>*
+    : self::DynamicClass::field1 = field1, self::DynamicClass::field2 = field2, super core::Object::•()
+    ;
+  method method() → dynamic
+    return this.{self::DynamicClass::field1}.*(this.{self::DynamicClass::field2});
+}
+class NumClass<T extends core::num* = core::num*, S extends self::NumClass::T* = core::num*> extends core::Object {
+  generic-covariant-impl field self::NumClass::T* field1;
+  generic-covariant-impl field self::NumClass::S* field2;
+  constructor •(self::NumClass::T* field1, self::NumClass::S* field2) → self::NumClass<self::NumClass::T*, self::NumClass::S*>*
+    : self::NumClass::field1 = field1, self::NumClass::field2 = field2, super core::Object::•()
+    ;
+  method method1() → core::num*
+    return this.{self::NumClass::field1}.{core::num::*}(this.{self::NumClass::field2});
+  method method2() → core::num*
+    return this.{self::NumClass::field1}.{core::num::+}(invalid-expression "pkg/front_end/testcases/general/type_variable_bound_access.dart:22:36: Error: The getter 'length' isn't defined for the class 'num'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'length'.
+  num method2() => field1 + field2.length;
+                                   ^^^^^^" as{TypeError} core::num*);
+}
+static method main() → dynamic {
+  new self::DynamicClass::•<core::num*, core::int*>(0.5, 2).{self::DynamicClass::method}();
+  new self::NumClass::•<core::num*, core::double*>(2, 0.5).{self::NumClass::method1}();
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_10.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_10.yaml
new file mode 100644
index 0000000..abcb6aa
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_10.yaml
@@ -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.md file.
+
+# Compile an application with a number of modules.
+# Recompile the same thing again and make sure the calculated dependencies are
+# the same.
+
+type: newworld
+strong: true
+modules:
+  module:
+    module/a.dart: |
+      import 'package:module/b.dart';
+
+      class A extends A2<B> { }
+      class A2<T> { }
+    module/b.dart: |
+      class B { }
+    module/.packages: |
+      module:.
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        import 'package:module/a.dart';
+        class Foo extends A {}
+      .packages: |
+        module:module
+    modules:
+      - module
+    expectedLibraryCount: 3
+    neededDillLibraries:
+      - package:module/a.dart
+      - package:module/b.dart
+    expectedContent:
+      org-dartlang-test:///main.dart:
+        - Class Foo
+      package:module/a.dart:
+        - Class A
+        - Class A2
+      package:module/b.dart:
+        - Class B
+  - entry: main.dart
+    worldType: updated
+    expectInitializeFromDill: false
+    # Nothing actually updated, as such everything is expected as before.
+    modules:
+      - module
+    expectedLibraryCount: 3
+    neededDillLibraries:
+      - package:module/a.dart
+      - package:module/b.dart
+    expectedContent:
+      org-dartlang-test:///main.dart:
+        - Class Foo
+      package:module/a.dart:
+        - Class A
+        - Class A2
+      package:module/b.dart:
+        - Class B
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_11.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_11.yaml
new file mode 100644
index 0000000..a4a6cd9
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_11.yaml
@@ -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.md file.
+
+# Compile an application with a number of modules.
+# Recompile the same thing again and make sure the calculated dependencies are
+# the same.
+
+type: newworld
+strong: true
+modules:
+  module:
+    module/a.dart: |
+      import 'package:module/b.dart';
+
+      class A implements A2<B> { }
+      class A2<T> { }
+    module/b.dart: |
+      class B { }
+    module/.packages: |
+      module:.
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        import 'package:module/a.dart';
+        class Foo extends A {}
+      .packages: |
+        module:module
+    modules:
+      - module
+    expectedLibraryCount: 3
+    neededDillLibraries:
+      - package:module/a.dart
+      - package:module/b.dart
+    expectedContent:
+      org-dartlang-test:///main.dart:
+        - Class Foo
+      package:module/a.dart:
+        - Class A
+        - Class A2
+      package:module/b.dart:
+        - Class B
+  - entry: main.dart
+    worldType: updated
+    expectInitializeFromDill: false
+    # Nothing actually updated, as such everything is expected as before.
+    modules:
+      - module
+    expectedLibraryCount: 3
+    neededDillLibraries:
+      - package:module/a.dart
+      - package:module/b.dart
+    expectedContent:
+      org-dartlang-test:///main.dart:
+        - Class Foo
+      package:module/a.dart:
+        - Class A
+        - Class A2
+      package:module/b.dart:
+        - Class B
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_12.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_12.yaml
new file mode 100644
index 0000000..4f4762e
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_12.yaml
@@ -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.md file.
+
+# Compile an application with a modules that isn't used, but,
+# which - if loaded - pulls in more of itself.
+
+type: newworld
+strong: true
+modules:
+  module:
+    module/a.dart: |
+      import 'package:module/b.dart';
+      class A { }
+    module/b.dart: |
+      export 'package:module/a.dart';
+      class B { }
+    module/c.dart: |
+      export 'package:module/d.dart';
+      class C { }
+    module/d.dart: |
+      import 'package:module/c.dart';
+      class D { }
+    module/.packages: |
+      module:.
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        class Foo {}
+      .packages: |
+        module:module
+    modules:
+      - module
+    expectedLibraryCount: 1
+    # We don't import the module, and thus don't use it.
+    neededDillLibraries: []
+    expectedContent:
+      org-dartlang-test:///main.dart:
+        - Class Foo
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_9.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_9.yaml
new file mode 100644
index 0000000..03cc5bd
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_9.yaml
@@ -0,0 +1,70 @@
+# 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.
+
+# Compile an application with a number of modules.
+# Recompile the same thing again and make sure the calculated dependencies are
+# the same.
+
+type: newworld
+strong: true
+modules:
+  moduleA:
+    moduleA/a.dart: |
+      export 'package:moduleB/b.dart';
+
+      class A { }
+    moduleA/.packages: |
+      moduleA:.
+      moduleB:../moduleB
+  moduleB:
+    moduleB/b.dart: |
+      class B {
+        int foo = 42;
+      }
+    moduleB/.packages: |
+      moduleB:.
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        import "package:moduleA/a.dart";
+
+        main() {
+          A a = new A();
+        }
+      .packages: |
+        moduleA:moduleA
+        moduleB:moduleB
+    modules:
+      - moduleA
+      - moduleB
+    expectedLibraryCount: 3
+    neededDillLibraries:
+      - package:moduleA/a.dart
+      - package:moduleB/b.dart
+    expectedContent:
+      org-dartlang-test:///main.dart:
+        - Procedure main
+      package:moduleA/a.dart:
+        - Class A
+      package:moduleB/b.dart:
+        - Class B
+  - entry: main.dart
+    worldType: updated
+    expectInitializeFromDill: false
+    # Nothing actually updated, as such everything is expected as before.
+    modules:
+      - moduleA
+      - moduleB
+    expectedLibraryCount: 3
+    neededDillLibraries:
+      - package:moduleA/a.dart
+      - package:moduleB/b.dart
+    expectedContent:
+      org-dartlang-test:///main.dart:
+        - Procedure main
+      package:moduleA/a.dart:
+        - Class A
+      package:moduleB/b.dart:
+        - Class B
\ No newline at end of file
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart
index bc39d50..5e47a90 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart
@@ -8,7 +8,7 @@
 import 'dart:async';
 
 main() async {
-  var /*@ type=() ->* Future<Null*>* */ f = /*@ returnType=Future<Null*>* */ () async {
+  var /*@ type=() ->* Future<Null?>* */ f = /*@ returnType=Future<Null?>* */ () async {
     return null;
   };
   Future y = f();
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.strong.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.strong.expect
index c94fcd7..e0504e6 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.strong.expect
@@ -6,7 +6,7 @@
 import "dart:async";
 
 static method main() → dynamic async {
-  () →* asy::Future<core::Null*>* f = () → asy::Future<core::Null*>* async {
+  () →* asy::Future<core::Null?>* f = () → asy::Future<core::Null?>* async {
     return null;
   };
   asy::Future<dynamic>* y = f.call();
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.strong.transformed.expect
index 77ac3db..e8faa37 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.strong.transformed.expect
@@ -18,9 +18,9 @@
     try {
       #L1:
       {
-        () →* asy::Future<core::Null*>* f = () → asy::Future<core::Null*>* /* originally async */ {
-          final asy::_AsyncAwaitCompleter<core::Null*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::Null*>();
-          asy::FutureOr<core::Null*>* :return_value;
+        () →* asy::Future<core::Null?>* f = () → asy::Future<core::Null?>* /* originally async */ {
+          final asy::_AsyncAwaitCompleter<core::Null?>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::Null?>();
+          asy::FutureOr<core::Null?>* :return_value;
           dynamic :async_stack_trace;
           dynamic :async_op_then;
           dynamic :async_op_error;
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart
index 0fcd324..9b6202f 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart
@@ -8,7 +8,7 @@
 import 'dart:async';
 
 main() async {
-  var /*@ type=() ->* Stream<Null*>* */ f = /*@ returnType=Stream<Null*>* */ () async* {
+  var /*@ type=() ->* Stream<Null?>* */ f = /*@ returnType=Stream<Null?>* */ () async* {
     yield null;
   };
   Stream y = f();
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.strong.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.strong.expect
index 399d883..3bfdf39 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.strong.expect
@@ -6,7 +6,7 @@
 import "dart:async";
 
 static method main() → dynamic async {
-  () →* asy::Stream<core::Null*>* f = () → asy::Stream<core::Null*>* async* {
+  () →* asy::Stream<core::Null?>* f = () → asy::Stream<core::Null?>* async* {
     yield null;
   };
   asy::Stream<dynamic>* y = f.call();
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.strong.transformed.expect
index 1c649f3..ae912fe 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.strong.transformed.expect
@@ -18,8 +18,8 @@
     try {
       #L1:
       {
-        () →* asy::Stream<core::Null*>* f = () → asy::Stream<core::Null*>* /* originally async* */ {
-          asy::_AsyncStarStreamController<core::Null*>* :controller;
+        () →* asy::Stream<core::Null?>* f = () → asy::Stream<core::Null?>* /* originally async* */ {
+          asy::_AsyncStarStreamController<core::Null?>* :controller;
           dynamic :controller_stream;
           dynamic :async_stack_trace;
           dynamic :async_op_then;
@@ -49,7 +49,7 @@
           :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
           :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
           :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
-          :controller = new asy::_AsyncStarStreamController::•<core::Null*>(:async_op);
+          :controller = new asy::_AsyncStarStreamController::•<core::Null?>(:async_op);
           :controller_stream = :controller.{asy::_AsyncStarStreamController::stream};
           return :controller_stream;
         };
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart
index 192fdd0..ff64ba7 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart
@@ -9,18 +9,18 @@
 void foo(int f(Object _)) {}
 
 test() {
-  var /*@ type=(Object*) ->* Null* */ f = /*@ returnType=Null* */ (Object x) {
+  var /*@ type=(Object*) ->* Null? */ f = /*@ returnType=Null? */ (Object x) {
     return null;
   };
   String y = f(42);
 
-  f = /*error:INVALID_CAST_FUNCTION_EXPR*/ /*@ returnType=Null* */ (/*@ type=Object* */ x) =>
+  f = /*error:INVALID_CAST_FUNCTION_EXPR*/ /*@ returnType=Null? */ (/*@ type=Object* */ x) =>
       'hello';
 
-  foo(/*@ returnType=Null* */ (/*@ type=Object* */ x) {
+  foo(/*@ returnType=Null? */ (/*@ type=Object* */ x) {
     return null;
   });
-  foo(/*@ returnType=Null* */ (/*@ type=Object* */ x) {
+  foo(/*@ returnType=Null? */ (/*@ type=Object* */ x) {
     throw "not implemented";
   });
 }
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.strong.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.strong.expect
index 851fe91..c1bf65f 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.strong.expect
@@ -5,15 +5,15 @@
 static field dynamic h = null;
 static method foo((core::Object*) →* core::int* f) → void {}
 static method test() → dynamic {
-  (core::Object*) →* core::Null* f = (core::Object* x) → core::Null* {
+  (core::Object*) →* core::Null? f = (core::Object* x) → core::Null? {
     return null;
   };
   core::String* y = f.call(42);
-  f = (core::Object* x) → core::Null* => "hello" as{TypeError} core::Null*;
-  self::foo((core::Object* x) → core::Null* {
+  f = (core::Object* x) → core::Null? => "hello" as{TypeError} core::Null?;
+  self::foo((core::Object* x) → core::Null? {
     return null;
   });
-  self::foo((core::Object* x) → core::Null* {
+  self::foo((core::Object* x) → core::Null? {
     throw "not implemented";
   });
 }
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.strong.transformed.expect
index 851fe91..c1bf65f 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.strong.transformed.expect
@@ -5,15 +5,15 @@
 static field dynamic h = null;
 static method foo((core::Object*) →* core::int* f) → void {}
 static method test() → dynamic {
-  (core::Object*) →* core::Null* f = (core::Object* x) → core::Null* {
+  (core::Object*) →* core::Null? f = (core::Object* x) → core::Null? {
     return null;
   };
   core::String* y = f.call(42);
-  f = (core::Object* x) → core::Null* => "hello" as{TypeError} core::Null*;
-  self::foo((core::Object* x) → core::Null* {
+  f = (core::Object* x) → core::Null? => "hello" as{TypeError} core::Null?;
+  self::foo((core::Object* x) → core::Null? {
     return null;
   });
-  self::foo((core::Object* x) → core::Null* {
+  self::foo((core::Object* x) → core::Null? {
     throw "not implemented";
   });
 }
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.type_promotion.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.type_promotion.expect
index 78cf9d6d..2fa431c 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.type_promotion.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart.type_promotion.expect
@@ -1,3 +1,3 @@
 pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync.dart:17:5: Context: Write to f@353
-  f = /*error:INVALID_CAST_FUNCTION_EXPR*/ /*@ returnType=Null* */ (/*@ type=Object* */ x) =>
+  f = /*error:INVALID_CAST_FUNCTION_EXPR*/ /*@ returnType=Null? */ (/*@ type=Object* */ x) =>
     ^
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart
index e4c6fe0..abfa763 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart
@@ -6,7 +6,7 @@
 library test;
 
 main() {
-  var /*@ type=() ->* Iterable<Null*>* */ f = /*@ returnType=Iterable<Null*>* */ () sync* {
+  var /*@ type=() ->* Iterable<Null?>* */ f = /*@ returnType=Iterable<Null?>* */ () sync* {
     yield null;
   };
   Iterable y = f();
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.strong.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.strong.expect
index d55bbde..96ec582 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 static method main() → dynamic {
-  () →* core::Iterable<core::Null*>* f = () → core::Iterable<core::Null*>* sync* {
+  () →* core::Iterable<core::Null?>* f = () → core::Iterable<core::Null?>* sync* {
     yield null;
   };
   core::Iterable<dynamic>* y = f.call();
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.strong.transformed.expect
index 843ea40..f94cf54 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.strong.transformed.expect
@@ -3,10 +3,10 @@
 import "dart:core" as core;
 
 static method main() → dynamic {
-  () →* core::Iterable<core::Null*>* f = () → core::Iterable<core::Null*>* /* originally sync* */ {
+  () →* core::Iterable<core::Null?>* f = () → core::Iterable<core::Null?>* /* originally sync* */ {
     dynamic :await_jump_var = 0;
     dynamic :await_ctx_var;
-    function :sync_op(core::_SyncIterator<core::Null*>* :iterator) → core::bool* yielding {
+    function :sync_op(core::_SyncIterator<core::Null?>* :iterator) → core::bool* yielding {
       {
         {
           :iterator.{core::_SyncIterator::_current} = null;
@@ -15,7 +15,7 @@
       }
       return false;
     }
-    return new core::_SyncIterable::•<core::Null*>(:sync_op);
+    return new core::_SyncIterable::•<core::Null?>(:sync_op);
   };
   core::Iterable<dynamic>* y = f.call();
   core::Iterable<core::String*>* z = f.call();
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart b/pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart
index 44aca46..4ca0960 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart
@@ -7,9 +7,9 @@
 
 test1() {
   List<int> o;
-  var /*@ type=Iterable<Null*>* */ y =
-      o. /*@ typeArgs=Null* */ /*@target=Iterable::map*/ map(
-          /*@ returnType=Null* */ (/*@ type=int* */ x) {});
+  var /*@ type=Iterable<Null?>* */ y =
+      o. /*@ typeArgs=Null? */ /*@target=Iterable::map*/ map(
+          /*@ returnType=Null? */ (/*@ type=int* */ x) {});
   Iterable<int> z = y;
 }
 
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart.strong.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart.strong.expect
index a3d94e2..ae81c76 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart.strong.expect
@@ -4,7 +4,7 @@
 
 static method test1() → dynamic {
   core::List<core::int*>* o;
-  core::Iterable<core::Null*>* y = o.{core::Iterable::map}<core::Null*>((core::int* x) → core::Null* {});
+  core::Iterable<core::Null?>* y = o.{core::Iterable::map}<core::Null?>((core::int* x) → core::Null? {});
   core::Iterable<core::int*>* z = y;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart.strong.transformed.expect
index a3d94e2..ae81c76 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_no_return.dart.strong.transformed.expect
@@ -4,7 +4,7 @@
 
 static method test1() → dynamic {
   core::List<core::int*>* o;
-  core::Iterable<core::Null*>* y = o.{core::Iterable::map}<core::Null*>((core::int* x) → core::Null* {});
+  core::Iterable<core::Null?>* y = o.{core::Iterable::map}<core::Null?>((core::int* x) → core::Null? {});
   core::Iterable<core::int*>* z = y;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart b/pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart
index dad3714..30d096e 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart
@@ -6,24 +6,24 @@
 library test;
 
 main() {
-  var /*@ type=() ->* Null* */ a = /*@ returnType=Null* */ () {};
-  var /*@ type=() ->* Null* */ b = /*@ returnType=Null* */ () {
+  var /*@ type=() ->* Null? */ a = /*@ returnType=Null? */ () {};
+  var /*@ type=() ->* Null? */ b = /*@ returnType=Null? */ () {
     return;
   };
-  var /*@ type=() ->* Null* */ c = /*@ returnType=Null* */ () {
+  var /*@ type=() ->* Null? */ c = /*@ returnType=Null? */ () {
     return null;
   };
   var /*@ type=() ->* int* */ d = /*@ returnType=int* */ () {
     return 0;
   };
-  var /*@ type=(bool*) ->* Null* */ e = /*@ returnType=Null* */ (bool b) {
+  var /*@ type=(bool*) ->* Null? */ e = /*@ returnType=Null? */ (bool b) {
     if (b) {
       return;
     } else {
       return;
     }
   };
-  var /*@ type=(bool*) ->* Null* */ f = /*@ returnType=Null* */ (bool b) {
+  var /*@ type=(bool*) ->* Null? */ f = /*@ returnType=Null? */ (bool b) {
     if (b) {
       return;
     } else {
@@ -37,14 +37,14 @@
       return 0;
     }
   };
-  var /*@ type=(bool*) ->* Null* */ h = /*@ returnType=Null* */ (bool b) {
+  var /*@ type=(bool*) ->* Null? */ h = /*@ returnType=Null? */ (bool b) {
     if (b) {
       return null;
     } else {
       return;
     }
   };
-  var /*@ type=(bool*) ->* Null* */ i = /*@ returnType=Null* */ (bool b) {
+  var /*@ type=(bool*) ->* Null? */ i = /*@ returnType=Null? */ (bool b) {
     if (b) {
       return null;
     } else {
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart.strong.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart.strong.expect
index b6de6a5..3ccb306 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart.strong.expect
@@ -14,17 +14,17 @@
 import "dart:core" as core;
 
 static method main() → dynamic {
-  () →* core::Null* a = () → core::Null* {};
-  () →* core::Null* b = () → core::Null* {
+  () →* core::Null? a = () → core::Null? {};
+  () →* core::Null? b = () → core::Null? {
     return;
   };
-  () →* core::Null* c = () → core::Null* {
+  () →* core::Null? c = () → core::Null? {
     return null;
   };
   () →* core::int* d = () → core::int* {
     return 0;
   };
-  (core::bool*) →* core::Null* e = (core::bool* b) → core::Null* {
+  (core::bool*) →* core::Null? e = (core::bool* b) → core::Null? {
     if(b) {
       return;
     }
@@ -32,7 +32,7 @@
       return;
     }
   };
-  (core::bool*) →* core::Null* f = (core::bool* b) → core::Null* {
+  (core::bool*) →* core::Null? f = (core::bool* b) → core::Null? {
     if(b) {
       return;
     }
@@ -48,7 +48,7 @@
       return 0;
     }
   };
-  (core::bool*) →* core::Null* h = (core::bool* b) → core::Null* {
+  (core::bool*) →* core::Null? h = (core::bool* b) → core::Null? {
     if(b) {
       return null;
     }
@@ -56,7 +56,7 @@
       return;
     }
   };
-  (core::bool*) →* core::Null* i = (core::bool* b) → core::Null* {
+  (core::bool*) →* core::Null? i = (core::bool* b) → core::Null? {
     if(b) {
       return null;
     }
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart.strong.transformed.expect
index b6de6a5..3ccb306 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_returns.dart.strong.transformed.expect
@@ -14,17 +14,17 @@
 import "dart:core" as core;
 
 static method main() → dynamic {
-  () →* core::Null* a = () → core::Null* {};
-  () →* core::Null* b = () → core::Null* {
+  () →* core::Null? a = () → core::Null? {};
+  () →* core::Null? b = () → core::Null? {
     return;
   };
-  () →* core::Null* c = () → core::Null* {
+  () →* core::Null? c = () → core::Null? {
     return null;
   };
   () →* core::int* d = () → core::int* {
     return 0;
   };
-  (core::bool*) →* core::Null* e = (core::bool* b) → core::Null* {
+  (core::bool*) →* core::Null? e = (core::bool* b) → core::Null? {
     if(b) {
       return;
     }
@@ -32,7 +32,7 @@
       return;
     }
   };
-  (core::bool*) →* core::Null* f = (core::bool* b) → core::Null* {
+  (core::bool*) →* core::Null? f = (core::bool* b) → core::Null? {
     if(b) {
       return;
     }
@@ -48,7 +48,7 @@
       return 0;
     }
   };
-  (core::bool*) →* core::Null* h = (core::bool* b) → core::Null* {
+  (core::bool*) →* core::Null? h = (core::bool* b) → core::Null? {
     if(b) {
       return null;
     }
@@ -56,7 +56,7 @@
       return;
     }
   };
-  (core::bool*) →* core::Null* i = (core::bool* b) → core::Null* {
+  (core::bool*) →* core::Null? i = (core::bool* b) → core::Null? {
     if(b) {
       return null;
     }
diff --git a/pkg/front_end/testcases/inference/bottom_in_closure.dart b/pkg/front_end/testcases/inference/bottom_in_closure.dart
index c0f7ac8..b05f476 100644
--- a/pkg/front_end/testcases/inference/bottom_in_closure.dart
+++ b/pkg/front_end/testcases/inference/bottom_in_closure.dart
@@ -5,7 +5,7 @@
 /*@testedFeatures=inference*/
 library test;
 
-var v = /*@ returnType=Null* */ () => null;
+var v = /*@ returnType=Null? */ () => null;
 
 main() {
   v;
diff --git a/pkg/front_end/testcases/inference/bottom_in_closure.dart.outline.expect b/pkg/front_end/testcases/inference/bottom_in_closure.dart.outline.expect
index 5497bda..0eb1af7 100644
--- a/pkg/front_end/testcases/inference/bottom_in_closure.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/bottom_in_closure.dart.outline.expect
@@ -2,6 +2,6 @@
 import self as self;
 import "dart:core" as core;
 
-static field () →* core::Null* v;
+static field () →* core::Null? v;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/inference/bottom_in_closure.dart.strong.expect b/pkg/front_end/testcases/inference/bottom_in_closure.dart.strong.expect
index 15c380f..8325cbb 100644
--- a/pkg/front_end/testcases/inference/bottom_in_closure.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/bottom_in_closure.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-static field () →* core::Null* v = () → core::Null* => null;
+static field () →* core::Null? v = () → core::Null? => null;
 static method main() → dynamic {
   self::v;
 }
diff --git a/pkg/front_end/testcases/inference/bottom_in_closure.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/bottom_in_closure.dart.strong.transformed.expect
index 15c380f..8325cbb 100644
--- a/pkg/front_end/testcases/inference/bottom_in_closure.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/bottom_in_closure.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-static field () →* core::Null* v = () → core::Null* => null;
+static field () →* core::Null? v = () → core::Null? => null;
 static method main() → dynamic {
   self::v;
 }
diff --git a/pkg/front_end/testcases/inference/bug31133.dart b/pkg/front_end/testcases/inference/bug31133.dart
index c9680f4..b5ff4bf 100644
--- a/pkg/front_end/testcases/inference/bug31133.dart
+++ b/pkg/front_end/testcases/inference/bug31133.dart
@@ -7,10 +7,18 @@
 
 void test() {
   var /*@ type=int* */ i = 0;
-  for (i++; i /*@target=num::<*/ < 10; i++) {}
-  for (++i; i /*@target=num::<*/ < 10; i++) {}
-  for (i--; i /*@target=num::>=*/ >= 0; i--) {}
-  for (--i; i /*@target=num::>=*/ >= 0; i--) {}
+  for (i /*@ target=num::+ */ ++;
+      i /*@target=num::<*/ < 10;
+      i /*@ target=num::+ */ ++) {}
+  for (/*@ target=num::+ */ ++i;
+      i /*@target=num::<*/ < 10;
+      i /*@ target=num::+ */ ++) {}
+  for (i /*@ target=num::- */ --;
+      i /*@target=num::>=*/ >= 0;
+      i /*@ target=num::- */ --) {}
+  for (/*@ target=num::- */ --i;
+      i /*@target=num::>=*/ >= 0;
+      i /*@ target=num::- */ --) {}
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/bug31133.dart.type_promotion.expect b/pkg/front_end/testcases/inference/bug31133.dart.type_promotion.expect
index a8c2fb5..bf317e2 100644
--- a/pkg/front_end/testcases/inference/bug31133.dart.type_promotion.expect
+++ b/pkg/front_end/testcases/inference/bug31133.dart.type_promotion.expect
@@ -1,24 +1,24 @@
-pkg/front_end/testcases/inference/bug31133.dart:10:9: Context: Write to i@299
-  for (i++; i /*@target=num::<*/ < 10; i++) {}
-        ^^
-pkg/front_end/testcases/inference/bug31133.dart:10:41: Context: Write to i@299
-  for (i++; i /*@target=num::<*/ < 10; i++) {}
-                                        ^^
-pkg/front_end/testcases/inference/bug31133.dart:11:8: Context: Write to i@299
-  for (++i; i /*@target=num::<*/ < 10; i++) {}
-       ^^
-pkg/front_end/testcases/inference/bug31133.dart:11:41: Context: Write to i@299
-  for (++i; i /*@target=num::<*/ < 10; i++) {}
-                                        ^^
-pkg/front_end/testcases/inference/bug31133.dart:12:9: Context: Write to i@299
-  for (i--; i /*@target=num::>=*/ >= 0; i--) {}
-        ^^
-pkg/front_end/testcases/inference/bug31133.dart:12:42: Context: Write to i@299
-  for (i--; i /*@target=num::>=*/ >= 0; i--) {}
-                                         ^^
-pkg/front_end/testcases/inference/bug31133.dart:13:8: Context: Write to i@299
-  for (--i; i /*@target=num::>=*/ >= 0; i--) {}
-       ^^
-pkg/front_end/testcases/inference/bug31133.dart:13:42: Context: Write to i@299
-  for (--i; i /*@target=num::>=*/ >= 0; i--) {}
-                                         ^^
+pkg/front_end/testcases/inference/bug31133.dart:10:31: Context: Write to i@299
+  for (i /*@ target=num::+ */ ++;
+                              ^^
+pkg/front_end/testcases/inference/bug31133.dart:12:30: Context: Write to i@299
+      i /*@ target=num::+ */ ++) {}
+                             ^^
+pkg/front_end/testcases/inference/bug31133.dart:13:29: Context: Write to i@299
+  for (/*@ target=num::+ */ ++i;
+                            ^^
+pkg/front_end/testcases/inference/bug31133.dart:15:30: Context: Write to i@299
+      i /*@ target=num::+ */ ++) {}
+                             ^^
+pkg/front_end/testcases/inference/bug31133.dart:16:31: Context: Write to i@299
+  for (i /*@ target=num::- */ --;
+                              ^^
+pkg/front_end/testcases/inference/bug31133.dart:18:30: Context: Write to i@299
+      i /*@ target=num::- */ --) {}
+                             ^^
+pkg/front_end/testcases/inference/bug31133.dart:19:29: Context: Write to i@299
+  for (/*@ target=num::- */ --i;
+                            ^^
+pkg/front_end/testcases/inference/bug31133.dart:21:30: Context: Write to i@299
+      i /*@ target=num::- */ --) {}
+                             ^^
diff --git a/pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart b/pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart
index 45cfec1..da3d184 100644
--- a/pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart
+++ b/pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart
@@ -10,13 +10,13 @@
   var /*@ type=dynamic */ b = null;
   var /*@ type=dynamic */ c = throw 'foo';
   var /*@ type=() ->* int* */ d = /*@ returnType=int* */ () => 0;
-  var /*@ type=() ->* Null* */ e = /*@ returnType=Null* */ () => null;
+  var /*@ type=() ->* Null? */ e = /*@ returnType=Null? */ () => null;
   var /*@ type=() ->* <BottomType> */ f = /*@ returnType=<BottomType> */ () =>
       throw 'foo';
   var /*@ type=() ->* int* */ g = /*@ returnType=int* */ () {
     return 0;
   };
-  var /*@ type=() ->* Null* */ h = /*@ returnType=Null* */ () {
+  var /*@ type=() ->* Null? */ h = /*@ returnType=Null? */ () {
     return null;
   };
   var /*@ type=() ->* <BottomType> */ i = /*@ returnType=<BottomType> */ () {
diff --git a/pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart.strong.expect b/pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart.strong.expect
index a4811d3..6d3a4af 100644
--- a/pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart.strong.expect
@@ -7,12 +7,12 @@
   dynamic b = null;
   dynamic c = throw "foo";
   () →* core::int* d = () → core::int* => 0;
-  () →* core::Null* e = () → core::Null* => null;
+  () →* core::Null? e = () → core::Null? => null;
   () →* <BottomType>f = () → <BottomType>=> throw "foo";
   () →* core::int* g = () → core::int* {
     return 0;
   };
-  () →* core::Null* h = () → core::Null* {
+  () →* core::Null? h = () → core::Null? {
     return null;
   };
   () →* <BottomType>i = () → <BottomType>{
diff --git a/pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart.strong.transformed.expect
index a4811d3..6d3a4af 100644
--- a/pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/coerce_bottom_and_null_types.dart.strong.transformed.expect
@@ -7,12 +7,12 @@
   dynamic b = null;
   dynamic c = throw "foo";
   () →* core::int* d = () → core::int* => 0;
-  () →* core::Null* e = () → core::Null* => null;
+  () →* core::Null? e = () → core::Null? => null;
   () →* <BottomType>f = () → <BottomType>=> throw "foo";
   () →* core::int* g = () → core::int* {
     return 0;
   };
-  () →* core::Null* h = () → core::Null* {
+  () →* core::Null? h = () → core::Null? {
     return null;
   };
   () →* <BottomType>i = () → <BottomType>{
diff --git a/pkg/front_end/testcases/inference/complex_predecrement.dart b/pkg/front_end/testcases/inference/complex_predecrement.dart
index ed84362..02b6f5a 100644
--- a/pkg/front_end/testcases/inference/complex_predecrement.dart
+++ b/pkg/front_end/testcases/inference/complex_predecrement.dart
@@ -7,5 +7,6 @@
 
 main() {
   var /*@ type=List<int*>* */ foo = /*@ typeArgs=int* */ [1, 2, 3];
-  print(--foo /*@target=List::[]=*/ [0]);
+  print(/*@ target=num::- */ --foo /*@target=List::[]*/ /*@target=List::[]=*/ [
+      0]);
 }
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.strong.transformed.expect
index 47257c7..0bd8d51 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.strong.transformed.expect
@@ -7,7 +7,7 @@
   abstract get t() → self::C::T*;
   abstract set t(generic-covariant-impl self::C::T* x) → void;
   static factory •<T extends core::Object* = dynamic>(self::C::•::T* t) → self::C<self::C::•::T*>*
-    let <T extends core::Object* = dynamic>(self::CImpl::•::T*) →* self::CImpl<self::CImpl::•::T*>* #redirecting_factory = self::CImpl::• in let self::C::•::T* #typeArg0 = null in invalid-expression;
+    let <T extends core::Object* = dynamic>(T*) →* self::CImpl<T*>* #redirecting_factory = self::CImpl::• in let self::C::•::T* #typeArg0 = null in invalid-expression;
 }
 class CImpl<T extends core::Object* = dynamic> extends core::Object implements self::C<self::CImpl::T*> {
   generic-covariant-impl field self::CImpl::T* t;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart
index 5ca6726..4481a40 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart
@@ -10,9 +10,12 @@
 }
 
 void test() {
-  for (@Foo(/*@ typeArgs=String* */ const []) int i = 0;
-       i /*@target=num::<*/< 1; i++) {}
-  for (@Foo(/*@ typeArgs=String* */ const []) int i in /*@ typeArgs=int* */[0]) {}
+  for (@Foo(/*@ typeArgs=String* */ const [])
+  int i = 0;
+      i /*@target=num::<*/ < 1;
+      i /*@ target=num::+ */ ++) {}
+  for (@Foo(/*@ typeArgs=String* */ const [])
+      int i in /*@ typeArgs=int* */ [0]) {}
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.type_promotion.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.type_promotion.expect
index 5b124f4..40956e2b4 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.type_promotion.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.type_promotion.expect
@@ -1,3 +1,3 @@
-pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart:14:34: Context: Write to i@370
-       i /*@target=num::<*/< 1; i++) {}
-                                 ^^
+pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart:16:30: Context: Write to i@372
+      i /*@ target=num::+ */ ++) {}
+                             ^^
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart
index c568ab4..1d09fe8 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart
@@ -11,7 +11,7 @@
 
 void test() {
   void f(@Foo(/*@ typeArgs=String* */ const []) /*@ type=dynamic */ x) {}
-  var /*@ type=(dynamic) ->* Null* */ x = /*@ returnType=Null* */ (@Foo(/*@ typeArgs=String* */ const []) /*@ type=dynamic */
+  var /*@ type=(dynamic) ->* Null? */ x = /*@ returnType=Null? */ (@Foo(/*@ typeArgs=String* */ const []) /*@ type=dynamic */
       x) {};
 }
 
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.expect
index 8bb1470..402205d 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.expect
@@ -9,7 +9,7 @@
 }
 static method test() → void {
   function f(@#C1 dynamic x) → void {}
-  (dynamic) →* core::Null* x = (@#C1 dynamic x) → core::Null* {};
+  (dynamic) →* core::Null? x = (@#C1 dynamic x) → core::Null? {};
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.transformed.expect
index 8bb1470..402205d 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.transformed.expect
@@ -9,7 +9,7 @@
 }
 static method test() → void {
   function f(@#C1 dynamic x) → void {}
-  (dynamic) →* core::Null* x = (@#C1 dynamic x) → core::Null* {};
+  (dynamic) →* core::Null? x = (@#C1 dynamic x) → core::Null? {};
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart
index 2eae17d..432c249 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart
@@ -11,8 +11,8 @@
 
 void test() {
   void f<@Foo(/*@ typeArgs=String* */ const []) T>() {}
-  var /*@ type=<@Foo::•(const <String*>[]) T extends Object* = dynamic>() ->* Null* */ x =
-      <@Foo(/*@ typeArgs=String* */ const []) T> /*@ returnType=Null* */ () {};
+  var /*@ type=<@Foo::•(const <String*>[]) T extends Object* = dynamic>() ->* Null? */ x =
+      <@Foo(/*@ typeArgs=String* */ const []) T> /*@ returnType=Null? */ () {};
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect
index 4fcf15f..5002d4f 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect
@@ -9,6 +9,6 @@
 }
 static method test() → void {
   function f<@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() → void {}
-  <@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() →* core::Null* x = <@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() → core::Null* {};
+  <@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() →* core::Null? x = <@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() → core::Null? {};
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect
index 4fcf15f..5002d4f 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect
@@ -9,6 +9,6 @@
 }
 static method test() → void {
   function f<@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() → void {}
-  <@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() →* core::Null* x = <@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() → core::Null* {};
+  <@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() →* core::Null? x = <@self::Foo::•(const <core::String*>[]) T extends core::Object* = dynamic>() → core::Null? {};
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart b/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart
index 907a37c..c8bea76 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart
@@ -9,7 +9,7 @@
 
 void test() {
   {
-    Function2<int, String> l0 = /*@ returnType=Null* */ (int x) => null;
+    Function2<int, String> l0 = /*@ returnType=Null? */ (int x) => null;
     Function2<int, String> l1 = /*@ returnType=String* */ (int x) => "hello";
     Function2<int, String>
         l2 = /*error:INVALID_ASSIGNMENT*/ /*@ returnType=String* */ (String x) =>
@@ -21,7 +21,7 @@
     };
   }
   {
-    Function2<int, String> l0 = /*@ returnType=Null* */ (/*@ type=int* */ x) => null;
+    Function2<int, String> l0 = /*@ returnType=Null? */ (/*@ type=int* */ x) => null;
     Function2<int, String> l1 = /*@ returnType=String* */ (/*@ type=int* */ x) =>
         "hello";
     Function2<int, String>
@@ -35,7 +35,7 @@
     };
   }
   {
-    Function2<int, List<String>> l0 = /*@ returnType=Null* */ (int x) => null;
+    Function2<int, List<String>> l0 = /*@ returnType=Null? */ (int x) => null;
     Function2<int, List<String>> l1 = /*@ returnType=List<String*>* */ (int
         x) => /*@ typeArgs=String* */ ["hello"];
     Function2<int, List<String>>
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.strong.expect
index 65b35d1..7c74d42 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.strong.expect
@@ -64,7 +64,7 @@
 typedef Function2<S extends core::Object* = dynamic, T extends core::Object* = dynamic> = (S*) →* T*;
 static method test() → void {
   {
-    (core::int*) →* core::String* l0 = (core::int* x) → core::Null* => null;
+    (core::int*) →* core::String* l0 = (core::int* x) → core::Null? => null;
     (core::int*) →* core::String* l1 = (core::int* x) → core::String* => "hello";
     (core::int*) →* core::String* l2 = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart:15:69: Error: A value of type 'String Function(String)' can't be assigned to a variable of type 'String Function(int)'.
 Try changing the type of the left hand side, or casting the right hand side to 'String Function(int)'.
@@ -82,7 +82,7 @@
     };
   }
   {
-    (core::int*) →* core::String* l0 = (core::int* x) → core::Null* => null;
+    (core::int*) →* core::String* l0 = (core::int* x) → core::Null? => null;
     (core::int*) →* core::String* l1 = (core::int* x) → core::String* => "hello";
     (core::int*) →* core::String* l2 = (core::int* x) → core::String* => let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart:29:13: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
 Try changing the type of the left hand side, or casting the right hand side to 'String'.
@@ -102,7 +102,7 @@
     };
   }
   {
-    (core::int*) →* core::List<core::String*>* l0 = (core::int* x) → core::Null* => null;
+    (core::int*) →* core::List<core::String*>* l0 = (core::int* x) → core::Null? => null;
     (core::int*) →* core::List<core::String*>* l1 = (core::int* x) → core::List<core::String*>* => <core::String*>["hello"];
     (core::int*) →* core::List<core::String*>* l2 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart:42:76: Error: A value of type 'List<String> Function(String)' can't be assigned to a variable of type 'List<String> Function(int)'.
  - 'List' is from 'dart:core'.
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.strong.transformed.expect
index 65b35d1..7c74d42 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.strong.transformed.expect
@@ -64,7 +64,7 @@
 typedef Function2<S extends core::Object* = dynamic, T extends core::Object* = dynamic> = (S*) →* T*;
 static method test() → void {
   {
-    (core::int*) →* core::String* l0 = (core::int* x) → core::Null* => null;
+    (core::int*) →* core::String* l0 = (core::int* x) → core::Null? => null;
     (core::int*) →* core::String* l1 = (core::int* x) → core::String* => "hello";
     (core::int*) →* core::String* l2 = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart:15:69: Error: A value of type 'String Function(String)' can't be assigned to a variable of type 'String Function(int)'.
 Try changing the type of the left hand side, or casting the right hand side to 'String Function(int)'.
@@ -82,7 +82,7 @@
     };
   }
   {
-    (core::int*) →* core::String* l0 = (core::int* x) → core::Null* => null;
+    (core::int*) →* core::String* l0 = (core::int* x) → core::Null? => null;
     (core::int*) →* core::String* l1 = (core::int* x) → core::String* => "hello";
     (core::int*) →* core::String* l2 = (core::int* x) → core::String* => let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart:29:13: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
 Try changing the type of the left hand side, or casting the right hand side to 'String'.
@@ -102,7 +102,7 @@
     };
   }
   {
-    (core::int*) →* core::List<core::String*>* l0 = (core::int* x) → core::Null* => null;
+    (core::int*) →* core::List<core::String*>* l0 = (core::int* x) → core::Null? => null;
     (core::int*) →* core::List<core::String*>* l1 = (core::int* x) → core::List<core::String*>* => <core::String*>["hello"];
     (core::int*) →* core::List<core::String*>* l2 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart:42:76: Error: A value of type 'List<String> Function(String)' can't be assigned to a variable of type 'List<String> Function(int)'.
  - 'List' is from 'dart:core'.
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart b/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart
index 35f9b53..bd01ae5 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart
@@ -9,7 +9,7 @@
   {
     String f<S>(int x) => null;
     var /*@ type=<S extends Object* = dynamic>(int*) ->* String* */ v = f;
-    v = <T> /*@ returnType=Null* */ (int x) => null;
+    v = <T> /*@ returnType=Null? */ (int x) => null;
     v = <T> /*@ returnType=String* */ (int x) => "hello";
     v = /*error:INVALID_ASSIGNMENT*/ <T> /*@ returnType=String* */ (String x) =>
         "hello";
@@ -21,7 +21,7 @@
   {
     String f<S>(int x) => null;
     var /*@ type=<S extends Object* = dynamic>(int*) ->* String* */ v = f;
-    v = <T> /*@ returnType=Null* */ (/*@ type=int* */ x) => null;
+    v = <T> /*@ returnType=Null? */ (/*@ type=int* */ x) => null;
     v = <T> /*@ returnType=String* */ (/*@ type=int* */ x) => "hello";
     v = /*info:INFERRED_TYPE_CLOSURE, error:INVALID_ASSIGNMENT*/ <
             T> /*@ returnType=String* */ (/*@ type=int* */ x) =>
@@ -36,7 +36,7 @@
   {
     List<String> f<S>(int x) => null;
     var /*@ type=<S extends Object* = dynamic>(int*) ->* List<String*>* */ v = f;
-    v = <T> /*@ returnType=Null* */ (int x) => null;
+    v = <T> /*@ returnType=Null? */ (int x) => null;
     v = <T> /*@ returnType=List<String*>* */ (int x) => /*@ typeArgs=String* */ [
           "hello"
         ];
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.strong.expect
index e415ae5..3adb8ba 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.strong.expect
@@ -66,7 +66,7 @@
     function f<S extends core::Object* = dynamic>(core::int* x) → core::String*
       return null;
     <S extends core::Object* = dynamic>(core::int*) →* core::String* v = f;
-    v = <T extends core::Object* = dynamic>(core::int* x) → core::Null* => null;
+    v = <T extends core::Object* = dynamic>(core::int* x) → core::Null? => null;
     v = <T extends core::Object* = dynamic>(core::int* x) → core::String* => "hello";
     v = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:14:68: Error: A value of type 'String Function<T>(String)' can't be assigned to a variable of type 'String Function<S>(int)'.
 Try changing the type of the left hand side, or casting the right hand side to 'String Function<S>(int)'.
@@ -87,7 +87,7 @@
     function f<S extends core::Object* = dynamic>(core::int* x) → core::String*
       return null;
     <S extends core::Object* = dynamic>(core::int*) →* core::String* v = f;
-    v = <T extends core::Object* = dynamic>(core::int* x) → core::Null* => null;
+    v = <T extends core::Object* = dynamic>(core::int* x) → core::Null? => null;
     v = <T extends core::Object* = dynamic>(core::int* x) → core::String* => "hello";
     v = <T extends core::Object* = dynamic>(core::int* x) → core::String* => let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:28:9: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
 Try changing the type of the left hand side, or casting the right hand side to 'String'.
@@ -110,7 +110,7 @@
     function f<S extends core::Object* = dynamic>(core::int* x) → core::List<core::String*>*
       return null;
     <S extends core::Object* = dynamic>(core::int*) →* core::List<core::String*>* v = f;
-    v = <T extends core::Object* = dynamic>(core::int* x) → core::Null* => null;
+    v = <T extends core::Object* = dynamic>(core::int* x) → core::Null? => null;
     v = <T extends core::Object* = dynamic>(core::int* x) → core::List<core::String*>* => <core::String*>["hello"];
     v = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:43:75: Error: A value of type 'List<String> Function<T>(String)' can't be assigned to a variable of type 'List<String> Function<S>(int)'.
  - 'List' is from 'dart:core'.
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.strong.transformed.expect
index e415ae5..3adb8ba 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.strong.transformed.expect
@@ -66,7 +66,7 @@
     function f<S extends core::Object* = dynamic>(core::int* x) → core::String*
       return null;
     <S extends core::Object* = dynamic>(core::int*) →* core::String* v = f;
-    v = <T extends core::Object* = dynamic>(core::int* x) → core::Null* => null;
+    v = <T extends core::Object* = dynamic>(core::int* x) → core::Null? => null;
     v = <T extends core::Object* = dynamic>(core::int* x) → core::String* => "hello";
     v = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:14:68: Error: A value of type 'String Function<T>(String)' can't be assigned to a variable of type 'String Function<S>(int)'.
 Try changing the type of the left hand side, or casting the right hand side to 'String Function<S>(int)'.
@@ -87,7 +87,7 @@
     function f<S extends core::Object* = dynamic>(core::int* x) → core::String*
       return null;
     <S extends core::Object* = dynamic>(core::int*) →* core::String* v = f;
-    v = <T extends core::Object* = dynamic>(core::int* x) → core::Null* => null;
+    v = <T extends core::Object* = dynamic>(core::int* x) → core::Null? => null;
     v = <T extends core::Object* = dynamic>(core::int* x) → core::String* => "hello";
     v = <T extends core::Object* = dynamic>(core::int* x) → core::String* => let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:28:9: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
 Try changing the type of the left hand side, or casting the right hand side to 'String'.
@@ -110,7 +110,7 @@
     function f<S extends core::Object* = dynamic>(core::int* x) → core::List<core::String*>*
       return null;
     <S extends core::Object* = dynamic>(core::int*) →* core::List<core::String*>* v = f;
-    v = <T extends core::Object* = dynamic>(core::int* x) → core::Null* => null;
+    v = <T extends core::Object* = dynamic>(core::int* x) → core::Null? => null;
     v = <T extends core::Object* = dynamic>(core::int* x) → core::List<core::String*>* => <core::String*>["hello"];
     v = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:43:75: Error: A value of type 'List<String> Function<T>(String)' can't be assigned to a variable of type 'List<String> Function<S>(int)'.
  - 'List' is from 'dart:core'.
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.type_promotion.expect b/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.type_promotion.expect
index 5f2ce87..370bfb82 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.type_promotion.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.type_promotion.expect
@@ -1,5 +1,5 @@
 pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:12:7: Context: Write to v@380
-    v = <T> /*@ returnType=Null* */ (int x) => null;
+    v = <T> /*@ returnType=Null? */ (int x) => null;
       ^
 pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:13:7: Context: Write to v@380
     v = <T> /*@ returnType=String* */ (int x) => "hello";
@@ -14,7 +14,7 @@
     v = <T> /*@ returnType=String* */ (int x) {
       ^
 pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:24:7: Context: Write to v@889
-    v = <T> /*@ returnType=Null* */ (/*@ type=int* */ x) => null;
+    v = <T> /*@ returnType=Null? */ (/*@ type=int* */ x) => null;
       ^
 pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:25:7: Context: Write to v@889
     v = <T> /*@ returnType=String* */ (/*@ type=int* */ x) => "hello";
@@ -29,7 +29,7 @@
     v = <T> /*@ returnType=String* */ (/*@ type=int* */ x) {
       ^
 pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:39:7: Context: Write to v@1531
-    v = <T> /*@ returnType=Null* */ (int x) => null;
+    v = <T> /*@ returnType=Null? */ (int x) => null;
       ^
 pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:40:7: Context: Write to v@1531
     v = <T> /*@ returnType=List<String*>* */ (int x) => /*@ typeArgs=String* */ [
diff --git a/pkg/front_end/testcases/inference/for_loop_empty_condition.dart b/pkg/front_end/testcases/inference/for_loop_empty_condition.dart
index ee2a836..95f321e 100644
--- a/pkg/front_end/testcases/inference/for_loop_empty_condition.dart
+++ b/pkg/front_end/testcases/inference/for_loop_empty_condition.dart
@@ -6,7 +6,7 @@
 library test;
 
 void test() {
-  for (num x = 0;; x++) {
+  for (num x = 0;; x /*@ target=num::+ */ ++) {
     if (x /*@target=num::>=*/ >= 10) break;
     if (x is int) {
       var /*@ type=int* */ y = /*@ promotedType=int* */ x;
diff --git a/pkg/front_end/testcases/inference/for_loop_empty_condition.dart.type_promotion.expect b/pkg/front_end/testcases/inference/for_loop_empty_condition.dart.type_promotion.expect
index 8598d0c..3f8990b 100644
--- a/pkg/front_end/testcases/inference/for_loop_empty_condition.dart.type_promotion.expect
+++ b/pkg/front_end/testcases/inference/for_loop_empty_condition.dart.type_promotion.expect
@@ -1,6 +1,6 @@
-pkg/front_end/testcases/inference/for_loop_empty_condition.dart:9:21: Context: Write to x@287
-  for (num x = 0;; x++) {
-                    ^^
+pkg/front_end/testcases/inference/for_loop_empty_condition.dart:9:43: Context: Write to x@287
+  for (num x = 0;; x /*@ target=num::+ */ ++) {
+                                          ^^
 pkg/front_end/testcases/inference/for_loop_empty_condition.dart:11:11: Context: Possible promotion of x@287
     if (x is int) {
           ^^
diff --git a/pkg/front_end/testcases/inference/for_loop_initializer_expression.dart b/pkg/front_end/testcases/inference/for_loop_initializer_expression.dart
index 4aa9f97..28684ac 100644
--- a/pkg/front_end/testcases/inference/for_loop_initializer_expression.dart
+++ b/pkg/front_end/testcases/inference/for_loop_initializer_expression.dart
@@ -7,7 +7,7 @@
 
 void test() {
   num x;
-  for (x = 0; x /*@target=num::<*/ < 10; x++) {
+  for (x = 0; x /*@target=num::<*/ < 10; x /*@ target=num::+ */ ++) {
     if (x is int) {
       var /*@ type=int* */ y = /*@ promotedType=int* */ x;
     }
diff --git a/pkg/front_end/testcases/inference/for_loop_initializer_expression.dart.type_promotion.expect b/pkg/front_end/testcases/inference/for_loop_initializer_expression.dart.type_promotion.expect
index 84d17d3..0a6dba0 100644
--- a/pkg/front_end/testcases/inference/for_loop_initializer_expression.dart.type_promotion.expect
+++ b/pkg/front_end/testcases/inference/for_loop_initializer_expression.dart.type_promotion.expect
@@ -1,9 +1,9 @@
 pkg/front_end/testcases/inference/for_loop_initializer_expression.dart:10:10: Context: Write to x@282
-  for (x = 0; x /*@target=num::<*/ < 10; x++) {
+  for (x = 0; x /*@target=num::<*/ < 10; x /*@ target=num::+ */ ++) {
          ^
-pkg/front_end/testcases/inference/for_loop_initializer_expression.dart:10:43: Context: Write to x@282
-  for (x = 0; x /*@target=num::<*/ < 10; x++) {
-                                          ^^
+pkg/front_end/testcases/inference/for_loop_initializer_expression.dart:10:65: Context: Write to x@282
+  for (x = 0; x /*@target=num::<*/ < 10; x /*@ target=num::+ */ ++) {
+                                                                ^^
 pkg/front_end/testcases/inference/for_loop_initializer_expression.dart:11:11: Context: Possible promotion of x@282
     if (x is int) {
           ^^
diff --git a/pkg/front_end/testcases/inference/for_loop_promotion.dart b/pkg/front_end/testcases/inference/for_loop_promotion.dart
index 3aa1cd8..e134425 100644
--- a/pkg/front_end/testcases/inference/for_loop_promotion.dart
+++ b/pkg/front_end/testcases/inference/for_loop_promotion.dart
@@ -6,7 +6,7 @@
 library test;
 
 void test() {
-  for (num x = 0; x /*@target=num::<*/ < 10; x++) {
+  for (num x = 0; x /*@target=num::<*/ < 10; x /*@ target=num::+ */ ++) {
     if (x is int) {
       var /*@ type=int* */ y = /*@ promotedType=int* */ x;
     }
diff --git a/pkg/front_end/testcases/inference/for_loop_promotion.dart.type_promotion.expect b/pkg/front_end/testcases/inference/for_loop_promotion.dart.type_promotion.expect
index 5cf87fe..9171867 100644
--- a/pkg/front_end/testcases/inference/for_loop_promotion.dart.type_promotion.expect
+++ b/pkg/front_end/testcases/inference/for_loop_promotion.dart.type_promotion.expect
@@ -1,6 +1,6 @@
-pkg/front_end/testcases/inference/for_loop_promotion.dart:9:47: Context: Write to x@287
-  for (num x = 0; x /*@target=num::<*/ < 10; x++) {
-                                              ^^
+pkg/front_end/testcases/inference/for_loop_promotion.dart:9:69: Context: Write to x@287
+  for (num x = 0; x /*@target=num::<*/ < 10; x /*@ target=num::+ */ ++) {
+                                                                    ^^
 pkg/front_end/testcases/inference/for_loop_promotion.dart:10:11: Context: Possible promotion of x@287
     if (x is int) {
           ^^
diff --git a/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart b/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart
index f7d4cd3..0477b7b 100644
--- a/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart
+++ b/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart
@@ -13,7 +13,7 @@
       . /*@ typeArgs=List<dynamic>* */ /*@target=Future::then*/ then(
           /*@ returnType=List<dynamic>* */ (/*@ type=int* */ x) => /*@ typeArgs=dynamic */ [])
       . /*@target=Future::whenComplete*/ whenComplete(
-          /*@ returnType=Null* */ () {});
+          /*@ returnType=Null? */ () {});
   b = f. /*@ typeArgs=List<int*>* */ /*@target=Future::then*/ then(
       /*@ returnType=List<int*>* */ (/*@ type=int* */ x) => /*@ typeArgs=int* */ []);
 }
diff --git a/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.strong.expect
index a535e1e..e129de8 100644
--- a/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.strong.expect
@@ -7,7 +7,7 @@
 
 static method test() → dynamic {
   asy::Future<core::int*>* f;
-  asy::Future<core::List<core::int*>*>* b = f.{asy::Future::then}<core::List<dynamic>*>((core::int* x) → core::List<dynamic>* => <dynamic>[]).{asy::Future::whenComplete}(() → core::Null* {}) as{TypeError} asy::Future<core::List<core::int*>*>*;
+  asy::Future<core::List<core::int*>*>* b = f.{asy::Future::then}<core::List<dynamic>*>((core::int* x) → core::List<dynamic>* => <dynamic>[]).{asy::Future::whenComplete}(() → core::Null? {}) as{TypeError} asy::Future<core::List<core::int*>*>*;
   b = f.{asy::Future::then}<core::List<core::int*>*>((core::int* x) → core::List<core::int*>* => <core::int*>[]);
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.strong.transformed.expect
index a535e1e..e129de8 100644
--- a/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.strong.transformed.expect
@@ -7,7 +7,7 @@
 
 static method test() → dynamic {
   asy::Future<core::int*>* f;
-  asy::Future<core::List<core::int*>*>* b = f.{asy::Future::then}<core::List<dynamic>*>((core::int* x) → core::List<dynamic>* => <dynamic>[]).{asy::Future::whenComplete}(() → core::Null* {}) as{TypeError} asy::Future<core::List<core::int*>*>*;
+  asy::Future<core::List<core::int*>*>* b = f.{asy::Future::then}<core::List<dynamic>*>((core::int* x) → core::List<dynamic>* => <dynamic>[]).{asy::Future::whenComplete}(() → core::Null? {}) as{TypeError} asy::Future<core::List<core::int*>*>*;
   b = f.{asy::Future::then}<core::List<core::int*>*>((core::int* x) → core::List<core::int*>* => <core::int*>[]);
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart b/pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart
index be4bd21..34aede8 100644
--- a/pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart
+++ b/pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart
@@ -12,6 +12,6 @@
 
 main() {
   var /*@ type=(num*) ->* List<int*>* */ v = /*@ typeArgs=(num*) ->* List<int*>* */ generic(
-      /*@ returnType=Null* */ (F f) => null,
-      /*@ returnType=Null* */ (G g) => null);
+      /*@ returnType=Null? */ (F f) => null,
+      /*@ returnType=Null? */ (G g) => null);
 }
diff --git a/pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart.strong.expect b/pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart.strong.expect
index e8ba7cf..4a105fb 100644
--- a/pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart.strong.expect
@@ -7,5 +7,5 @@
 static method generic<T extends core::Object* = dynamic>((self::generic::T*) →* dynamic a, (self::generic::T*) →* dynamic b) → self::generic::T*
   return null;
 static method main() → dynamic {
-  (core::num*) →* core::List<core::int*>* v = self::generic<(core::num*) →* core::List<core::int*>*>(((core::int*) →* core::Iterable<core::num*>* f) → core::Null* => null, ((core::double*) →* core::List<core::int*>* g) → core::Null* => null);
+  (core::num*) →* core::List<core::int*>* v = self::generic<(core::num*) →* core::List<core::int*>*>(((core::int*) →* core::Iterable<core::num*>* f) → core::Null? => null, ((core::double*) →* core::List<core::int*>* g) → core::Null? => null);
 }
diff --git a/pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart.strong.transformed.expect
index e8ba7cf..4a105fb 100644
--- a/pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_uses_greatest_lower_bound.dart.strong.transformed.expect
@@ -7,5 +7,5 @@
 static method generic<T extends core::Object* = dynamic>((self::generic::T*) →* dynamic a, (self::generic::T*) →* dynamic b) → self::generic::T*
   return null;
 static method main() → dynamic {
-  (core::num*) →* core::List<core::int*>* v = self::generic<(core::num*) →* core::List<core::int*>*>(((core::int*) →* core::Iterable<core::num*>* f) → core::Null* => null, ((core::double*) →* core::List<core::int*>* g) → core::Null* => null);
+  (core::num*) →* core::List<core::int*>* v = self::generic<(core::num*) →* core::List<core::int*>*>(((core::int*) →* core::Iterable<core::num*>* f) → core::Null? => null, ((core::double*) →* core::List<core::int*>* g) → core::Null? => null);
 }
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart b/pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart
index 74bb832..118957d 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_implicit_this.dart
@@ -23,17 +23,34 @@
 
   void test() {
     /*@target=Test::member*/ member = /*@ typeArgs=B* */ f();
-    /*@target=Test::member*/ member ??= /*@ typeArgs=B* */ f();
+
+    /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
     /*@target=Test::member*/ member += /*@ typeArgs=dynamic */ f();
+
     /*@target=Test::member*/ member *= /*@ typeArgs=dynamic */ f();
+
     /*@target=Test::member*/ member &= /*@ typeArgs=dynamic */ f();
+
     -- /*@target=Test::member*/ member;
+
     /*@target=Test::member*/ member--;
-    var /*@ type=B* */ v1 = /*@target=Test::member*/ member = /*@ typeArgs=B* */ f();
-    var /*@ type=B* */ v2 = /*@target=Test::member*/ member ??= /*@ typeArgs=B* */ f();
-    var /*@ type=B* */ v4 = /*@target=Test::member*/ member *= /*@ typeArgs=dynamic */ f();
-    var /*@ type=C* */ v5 = /*@target=Test::member*/ member &= /*@ typeArgs=dynamic */ f();
+
+    var /*@ type=B* */ v1 = /*@target=Test::member*/ member =
+        /*@ typeArgs=B* */ f();
+
+    var /*@ type=B* */ v2 = /*@target=Test::member*/ /*@target=Test::member*/
+        member /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
+    var /*@ type=B* */ v4 = /*@target=Test::member*/ member *=
+        /*@ typeArgs=dynamic */ f();
+
+    var /*@ type=C* */ v5 = /*@target=Test::member*/ member &=
+        /*@ typeArgs=dynamic */ f();
+
     var /*@ type=B* */ v6 = -- /*@target=Test::member*/ member;
+
     var /*@ type=B* */ v7 = /*@target=Test::member*/ member--;
   }
 }
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_implicit_this_upwards.dart b/pkg/front_end/testcases/inference/infer_assign_to_implicit_this_upwards.dart
index d60a4c3..0f111a2 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_implicit_this_upwards.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_implicit_this_upwards.dart
@@ -14,9 +14,14 @@
 
   void test() {
     var /*@ type=int* */ v1 = /*@target=Test1::t*/ t = getInt();
-    var /*@ type=int* */ v4 = /*@target=Test1::t*/ t ??= getInt();
+
+    var /*@ type=int* */ v4 = /*@target=Test1::t*/ /*@target=Test1::t*/ t
+        /*@ target=num::== */ ??= getInt();
+
     var /*@ type=int* */ v7 = /*@target=Test1::t*/ t += getInt();
+
     var /*@ type=int* */ v10 = ++ /*@target=Test1::t*/ t;
+
     var /*@ type=int* */ v11 = /*@target=Test1::t*/ t++;
   }
 }
@@ -26,15 +31,28 @@
 
   void test() {
     var /*@ type=int* */ v1 = /*@target=Test2::t*/ t = getInt();
+
     var /*@ type=num* */ v2 = /*@target=Test2::t*/ t = getNum();
+
     var /*@ type=double* */ v3 = /*@target=Test2::t*/ t = getDouble();
-    var /*@ type=num* */ v4 = /*@target=Test2::t*/ t ??= getInt();
-    var /*@ type=num* */ v5 = /*@target=Test2::t*/ t ??= getNum();
-    var /*@ type=num* */ v6 = /*@target=Test2::t*/ t ??= getDouble();
+
+    var /*@ type=num* */ v4 = /*@target=Test2::t*/ /*@target=Test2::t*/ t
+        /*@ target=num::== */ ??= getInt();
+
+    var /*@ type=num* */ v5 = /*@target=Test2::t*/ /*@target=Test2::t*/ t
+        /*@ target=num::== */ ??= getNum();
+
+    var /*@ type=num* */ v6 = /*@target=Test2::t*/ /*@target=Test2::t*/ t
+        /*@ target=num::== */ ??= getDouble();
+
     var /*@ type=num* */ v7 = /*@target=Test2::t*/ t += getInt();
+
     var /*@ type=num* */ v8 = /*@target=Test2::t*/ t += getNum();
+
     var /*@ type=num* */ v9 = /*@target=Test2::t*/ t += getDouble();
+
     var /*@ type=num* */ v10 = ++ /*@target=Test2::t*/ t;
+
     var /*@ type=num* */ v11 = /*@target=Test2::t*/ t++;
   }
 }
@@ -44,11 +62,18 @@
 
   void test3() {
     var /*@ type=double* */ v3 = /*@target=Test3::t*/ t = getDouble();
-    var /*@ type=double* */ v6 = /*@target=Test3::t*/ t ??= getDouble();
+
+    var /*@ type=double* */ v6 = /*@target=Test3::t*/ /*@target=Test3::t*/ t
+        /*@ target=num::== */ ??= getDouble();
+
     var /*@ type=double* */ v7 = /*@target=Test3::t*/ t += getInt();
+
     var /*@ type=double* */ v8 = /*@target=Test3::t*/ t += getNum();
+
     var /*@ type=double* */ v9 = /*@target=Test3::t*/ t += getDouble();
+
     var /*@ type=double* */ v10 = ++ /*@target=Test3::t*/ t;
+
     var /*@ type=double* */ v11 = /*@target=Test3::t*/ t++;
   }
 }
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_full.dart b/pkg/front_end/testcases/inference/infer_assign_to_index_full.dart
index 16a2336..d344928 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index_full.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_index_full.dart
@@ -26,26 +26,55 @@
 
   void test() {
     Test t = /*@ typeArgs=Test* */ f();
-    t /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()] = /*@ typeArgs=B* */ f();
-    t /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()] ??= /*@ typeArgs=B* */ f();
+
     t /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] += /*@ typeArgs=dynamic */ f();
-    t /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] *= /*@ typeArgs=dynamic */ f();
-    t /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] &= /*@ typeArgs=dynamic */ f();
-    --t /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()];
-    t /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()]--;
+        /*@ typeArgs=Index* */ f()] = /*@ typeArgs=B* */ f();
+
+    t /*@target=Test::[]*/ [/*@ typeArgs=Index* */ f()]
+        /*@ target=Object::== */ /*@ target=Test::[]= */
+        ??= /*@ typeArgs=B* */ f();
+
+    t /*@target=Test::[]*/ /*@target=Test::[]=*/ [/*@ typeArgs=Index* */ f()]
+        /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+    t /*@target=Test::[]*/ /*@target=Test::[]=*/ [/*@ typeArgs=Index* */ f()]
+        /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+    t /*@target=Test::[]*/ /*@target=Test::[]=*/ [/*@ typeArgs=Index* */ f()]
+        /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+    t /*@target=Test::[]*/ [/*@ typeArgs=Index* */ f()];
+
+    /*@ target=B::- */ --t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+        /*@ typeArgs=Index* */ f()];
+
+    t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+        /*@ typeArgs=Index* */ f()] /*@ target=B::- */ --;
+
     var /*@ type=B* */ v1 = t /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] = /*@ typeArgs=B* */ f();
-    var /*@ type=B* */ v2 = t /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] ??= /*@ typeArgs=B* */ f();
-    var /*@ type=B* */ v4 = t /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] *= /*@ typeArgs=dynamic */ f();
-    var /*@ type=C* */ v5 = t /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] &= /*@ typeArgs=dynamic */ f();
-    var /*@ type=B* */ v6 = --t /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()];
-    var /*@ type=B* */ v7 = t /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()]--;
+        /*@ typeArgs=Index* */ f()] = /*@ typeArgs=B* */ f();
+
+    var /*@ type=B* */ v2 = t /*@target=Test::[]*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=Object::== */ /*@ target=Test::[]= */
+        ??= /*@ typeArgs=B* */ f();
+
+    var /*@ type=B* */ v4 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+    var /*@ type=C* */ v5 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+    var /*@ type=B* */ v6 = t /*@target=Test::[]*/ [/*@ typeArgs=Index* */ f()];
+
+    var /*@ type=B* */ v7 =
+        /*@ target=B::- */ --t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()];
+
+    var /*@ type=B* */ v8 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+        /*@ typeArgs=Index* */ f()] /*@ target=B::- */ --;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_full.dart.strong.expect b/pkg/front_end/testcases/inference/infer_assign_to_index_full.dart.strong.expect
index 40716cc..4711ea5 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index_full.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_index_full.dart.strong.expect
@@ -39,19 +39,21 @@
   operator []=(self::Index* i, self::B* v) → void {}
   method test() → void {
     self::Test* t = self::f<self::Test*>();
-    t.{self::Test::[]=}(self::f<dynamic>() as{TypeError} self::Index*, self::f<self::B*>());
-    let final self::Test* #t1 = t in let final dynamic #t2 = self::f<dynamic>() in #t1.{self::Test::[]}(#t2 as{TypeError} self::Index*).{core::Object::==}(null) ?{self::B*} let final self::B* #t3 = self::f<self::B*>() in let final void #t4 = #t1.{self::Test::[]=}(#t2 as{TypeError} self::Index*, #t3) in #t3 : null;
-    let final self::Test* #t5 = t in let final dynamic #t6 = self::f<dynamic>() in #t5.{self::Test::[]=}(#t6 as{TypeError} self::Index*, #t5.{self::Test::[]}(#t6 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*);
-    let final self::Test* #t7 = t in let final dynamic #t8 = self::f<dynamic>() in #t7.{self::Test::[]=}(#t8 as{TypeError} self::Index*, #t7.{self::Test::[]}(#t8 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*));
-    let final self::Test* #t9 = t in let final dynamic #t10 = self::f<dynamic>() in #t9.{self::Test::[]=}(#t10 as{TypeError} self::Index*, #t9.{self::Test::[]}(#t10 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*));
-    let final self::Test* #t11 = t in let final dynamic #t12 = self::f<dynamic>() in let final self::B* #t13 = #t11.{self::Test::[]}(#t12 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t14 = #t11.{self::Test::[]=}(#t12 as{TypeError} self::Index*, #t13) in #t13;
-    let final self::Test* #t15 = t in let final dynamic #t16 = self::f<dynamic>() in #t15.{self::Test::[]=}(#t16 as{TypeError} self::Index*, #t15.{self::Test::[]}(#t16 as{TypeError} self::Index*).{self::B::-}(1));
-    self::B* v1 = let final self::Test* #t17 = t in let final dynamic #t18 = self::f<dynamic>() in let final self::B* #t19 = self::f<self::B*>() in let final void #t20 = #t17.{self::Test::[]=}(#t18 as{TypeError} self::Index*, #t19) in #t19;
-    self::B* v2 = let final self::Test* #t21 = t in let final dynamic #t22 = self::f<dynamic>() in let final self::B* #t23 = #t21.{self::Test::[]}(#t22 as{TypeError} self::Index*) in #t23.{core::Object::==}(null) ?{self::B*} let final self::B* #t24 = self::f<self::B*>() in let final void #t25 = #t21.{self::Test::[]=}(#t22 as{TypeError} self::Index*, #t24) in #t24 : #t23;
-    self::B* v4 = let final self::Test* #t26 = t in let final dynamic #t27 = self::f<dynamic>() in let final self::B* #t28 = #t26.{self::Test::[]}(#t27 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*) in let final void #t29 = #t26.{self::Test::[]=}(#t27 as{TypeError} self::Index*, #t28) in #t28;
-    self::C* v5 = let final self::Test* #t30 = t in let final dynamic #t31 = self::f<dynamic>() in let final self::C* #t32 = #t30.{self::Test::[]}(#t31 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*) in let final void #t33 = #t30.{self::Test::[]=}(#t31 as{TypeError} self::Index*, #t32) in #t32;
-    self::B* v6 = let final self::Test* #t34 = t in let final dynamic #t35 = self::f<dynamic>() in let final self::B* #t36 = #t34.{self::Test::[]}(#t35 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t37 = #t34.{self::Test::[]=}(#t35 as{TypeError} self::Index*, #t36) in #t36;
-    self::B* v7 = let final self::Test* #t38 = t in let final dynamic #t39 = self::f<dynamic>() in let final self::B* #t40 = #t38.{self::Test::[]}(#t39 as{TypeError} self::Index*) in let final void #t41 = #t38.{self::Test::[]=}(#t39 as{TypeError} self::Index*, #t40.{self::B::-}(1)) in #t40;
+    t.{self::Test::[]=}(self::f<self::Index*>(), self::f<self::B*>());
+    let final self::Test* #t1 = t in let final self::Index* #t2 = self::f<self::Index*>() in #t1.{self::Test::[]}(#t2).{core::Object::==}(null) ?{self::B*} #t1.{self::Test::[]=}(#t2, self::f<self::B*>()) : null;
+    let final self::Test* #t3 = t in let final self::Index* #t4 = self::f<self::Index*>() in #t3.{self::Test::[]=}(#t4, #t3.{self::Test::[]}(#t4).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*);
+    let final self::Test* #t5 = t in let final self::Index* #t6 = self::f<self::Index*>() in #t5.{self::Test::[]=}(#t6, #t5.{self::Test::[]}(#t6).{self::B::*}(self::f<self::B*>()));
+    let final self::Test* #t7 = t in let final self::Index* #t8 = self::f<self::Index*>() in #t7.{self::Test::[]=}(#t8, #t7.{self::Test::[]}(#t8).{self::B::&}(self::f<self::A*>()));
+    t.{self::Test::[]}(self::f<self::Index*>());
+    let final self::Test* #t9 = t in let final self::Index* #t10 = self::f<self::Index*>() in let final self::B* #t11 = #t9.{self::Test::[]}(#t10).{self::B::-}(1) in let final void #t12 = #t9.{self::Test::[]=}(#t10, #t11) in #t11;
+    let final self::Test* #t13 = t in let final self::Index* #t14 = self::f<self::Index*>() in #t13.{self::Test::[]=}(#t14, #t13.{self::Test::[]}(#t14).{self::B::-}(1));
+    self::B* v1 = let final self::Test* #t15 = t in let final self::Index* #t16 = self::f<self::Index*>() in let final self::B* #t17 = self::f<self::B*>() in let final void #t18 = #t15.{self::Test::[]=}(#t16, #t17) in #t17;
+    self::B* v2 = let final self::Test* #t19 = t in let final self::Index* #t20 = self::f<self::Index*>() in let final self::B* #t21 = #t19.{self::Test::[]}(#t20) in #t21.{core::Object::==}(null) ?{self::B*} let final self::B* #t22 = self::f<self::B*>() in let final void #t23 = #t19.{self::Test::[]=}(#t20, #t22) in #t22 : #t21;
+    self::B* v4 = let final self::Test* #t24 = t in let final self::Index* #t25 = self::f<self::Index*>() in let final self::B* #t26 = #t24.{self::Test::[]}(#t25).{self::B::*}(self::f<self::B*>()) in let final void #t27 = #t24.{self::Test::[]=}(#t25, #t26) in #t26;
+    self::C* v5 = let final self::Test* #t28 = t in let final self::Index* #t29 = self::f<self::Index*>() in let final self::C* #t30 = #t28.{self::Test::[]}(#t29).{self::B::&}(self::f<self::A*>()) in let final void #t31 = #t28.{self::Test::[]=}(#t29, #t30) in #t30;
+    self::B* v6 = t.{self::Test::[]}(self::f<self::Index*>());
+    self::B* v7 = let final self::Test* #t32 = t in let final self::Index* #t33 = self::f<self::Index*>() in let final self::B* #t34 = #t32.{self::Test::[]}(#t33).{self::B::-}(1) in let final void #t35 = #t32.{self::Test::[]=}(#t33, #t34) in #t34;
+    self::B* v8 = let final self::Test* #t36 = t in let final self::Index* #t37 = self::f<self::Index*>() in let final self::B* #t38 = #t36.{self::Test::[]}(#t37) in let final void #t39 = #t36.{self::Test::[]=}(#t37, #t38.{self::B::-}(1)) in #t38;
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_index_full.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_index_full.dart.strong.transformed.expect
index 40716cc..4711ea5 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_index_full.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_index_full.dart.strong.transformed.expect
@@ -39,19 +39,21 @@
   operator []=(self::Index* i, self::B* v) → void {}
   method test() → void {
     self::Test* t = self::f<self::Test*>();
-    t.{self::Test::[]=}(self::f<dynamic>() as{TypeError} self::Index*, self::f<self::B*>());
-    let final self::Test* #t1 = t in let final dynamic #t2 = self::f<dynamic>() in #t1.{self::Test::[]}(#t2 as{TypeError} self::Index*).{core::Object::==}(null) ?{self::B*} let final self::B* #t3 = self::f<self::B*>() in let final void #t4 = #t1.{self::Test::[]=}(#t2 as{TypeError} self::Index*, #t3) in #t3 : null;
-    let final self::Test* #t5 = t in let final dynamic #t6 = self::f<dynamic>() in #t5.{self::Test::[]=}(#t6 as{TypeError} self::Index*, #t5.{self::Test::[]}(#t6 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*);
-    let final self::Test* #t7 = t in let final dynamic #t8 = self::f<dynamic>() in #t7.{self::Test::[]=}(#t8 as{TypeError} self::Index*, #t7.{self::Test::[]}(#t8 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*));
-    let final self::Test* #t9 = t in let final dynamic #t10 = self::f<dynamic>() in #t9.{self::Test::[]=}(#t10 as{TypeError} self::Index*, #t9.{self::Test::[]}(#t10 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*));
-    let final self::Test* #t11 = t in let final dynamic #t12 = self::f<dynamic>() in let final self::B* #t13 = #t11.{self::Test::[]}(#t12 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t14 = #t11.{self::Test::[]=}(#t12 as{TypeError} self::Index*, #t13) in #t13;
-    let final self::Test* #t15 = t in let final dynamic #t16 = self::f<dynamic>() in #t15.{self::Test::[]=}(#t16 as{TypeError} self::Index*, #t15.{self::Test::[]}(#t16 as{TypeError} self::Index*).{self::B::-}(1));
-    self::B* v1 = let final self::Test* #t17 = t in let final dynamic #t18 = self::f<dynamic>() in let final self::B* #t19 = self::f<self::B*>() in let final void #t20 = #t17.{self::Test::[]=}(#t18 as{TypeError} self::Index*, #t19) in #t19;
-    self::B* v2 = let final self::Test* #t21 = t in let final dynamic #t22 = self::f<dynamic>() in let final self::B* #t23 = #t21.{self::Test::[]}(#t22 as{TypeError} self::Index*) in #t23.{core::Object::==}(null) ?{self::B*} let final self::B* #t24 = self::f<self::B*>() in let final void #t25 = #t21.{self::Test::[]=}(#t22 as{TypeError} self::Index*, #t24) in #t24 : #t23;
-    self::B* v4 = let final self::Test* #t26 = t in let final dynamic #t27 = self::f<dynamic>() in let final self::B* #t28 = #t26.{self::Test::[]}(#t27 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*) in let final void #t29 = #t26.{self::Test::[]=}(#t27 as{TypeError} self::Index*, #t28) in #t28;
-    self::C* v5 = let final self::Test* #t30 = t in let final dynamic #t31 = self::f<dynamic>() in let final self::C* #t32 = #t30.{self::Test::[]}(#t31 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*) in let final void #t33 = #t30.{self::Test::[]=}(#t31 as{TypeError} self::Index*, #t32) in #t32;
-    self::B* v6 = let final self::Test* #t34 = t in let final dynamic #t35 = self::f<dynamic>() in let final self::B* #t36 = #t34.{self::Test::[]}(#t35 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t37 = #t34.{self::Test::[]=}(#t35 as{TypeError} self::Index*, #t36) in #t36;
-    self::B* v7 = let final self::Test* #t38 = t in let final dynamic #t39 = self::f<dynamic>() in let final self::B* #t40 = #t38.{self::Test::[]}(#t39 as{TypeError} self::Index*) in let final void #t41 = #t38.{self::Test::[]=}(#t39 as{TypeError} self::Index*, #t40.{self::B::-}(1)) in #t40;
+    t.{self::Test::[]=}(self::f<self::Index*>(), self::f<self::B*>());
+    let final self::Test* #t1 = t in let final self::Index* #t2 = self::f<self::Index*>() in #t1.{self::Test::[]}(#t2).{core::Object::==}(null) ?{self::B*} #t1.{self::Test::[]=}(#t2, self::f<self::B*>()) : null;
+    let final self::Test* #t3 = t in let final self::Index* #t4 = self::f<self::Index*>() in #t3.{self::Test::[]=}(#t4, #t3.{self::Test::[]}(#t4).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*);
+    let final self::Test* #t5 = t in let final self::Index* #t6 = self::f<self::Index*>() in #t5.{self::Test::[]=}(#t6, #t5.{self::Test::[]}(#t6).{self::B::*}(self::f<self::B*>()));
+    let final self::Test* #t7 = t in let final self::Index* #t8 = self::f<self::Index*>() in #t7.{self::Test::[]=}(#t8, #t7.{self::Test::[]}(#t8).{self::B::&}(self::f<self::A*>()));
+    t.{self::Test::[]}(self::f<self::Index*>());
+    let final self::Test* #t9 = t in let final self::Index* #t10 = self::f<self::Index*>() in let final self::B* #t11 = #t9.{self::Test::[]}(#t10).{self::B::-}(1) in let final void #t12 = #t9.{self::Test::[]=}(#t10, #t11) in #t11;
+    let final self::Test* #t13 = t in let final self::Index* #t14 = self::f<self::Index*>() in #t13.{self::Test::[]=}(#t14, #t13.{self::Test::[]}(#t14).{self::B::-}(1));
+    self::B* v1 = let final self::Test* #t15 = t in let final self::Index* #t16 = self::f<self::Index*>() in let final self::B* #t17 = self::f<self::B*>() in let final void #t18 = #t15.{self::Test::[]=}(#t16, #t17) in #t17;
+    self::B* v2 = let final self::Test* #t19 = t in let final self::Index* #t20 = self::f<self::Index*>() in let final self::B* #t21 = #t19.{self::Test::[]}(#t20) in #t21.{core::Object::==}(null) ?{self::B*} let final self::B* #t22 = self::f<self::B*>() in let final void #t23 = #t19.{self::Test::[]=}(#t20, #t22) in #t22 : #t21;
+    self::B* v4 = let final self::Test* #t24 = t in let final self::Index* #t25 = self::f<self::Index*>() in let final self::B* #t26 = #t24.{self::Test::[]}(#t25).{self::B::*}(self::f<self::B*>()) in let final void #t27 = #t24.{self::Test::[]=}(#t25, #t26) in #t26;
+    self::C* v5 = let final self::Test* #t28 = t in let final self::Index* #t29 = self::f<self::Index*>() in let final self::C* #t30 = #t28.{self::Test::[]}(#t29).{self::B::&}(self::f<self::A*>()) in let final void #t31 = #t28.{self::Test::[]=}(#t29, #t30) in #t30;
+    self::B* v6 = t.{self::Test::[]}(self::f<self::Index*>());
+    self::B* v7 = let final self::Test* #t32 = t in let final self::Index* #t33 = self::f<self::Index*>() in let final self::B* #t34 = #t32.{self::Test::[]}(#t33).{self::B::-}(1) in let final void #t35 = #t32.{self::Test::[]=}(#t33, #t34) in #t34;
+    self::B* v8 = let final self::Test* #t36 = t in let final self::Index* #t37 = self::f<self::Index*>() in let final self::B* #t38 = #t36.{self::Test::[]}(#t37) in let final void #t39 = #t36.{self::Test::[]=}(#t37, #t38.{self::B::-}(1)) in #t38;
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_local.dart b/pkg/front_end/testcases/inference/infer_assign_to_local.dart
index d13afe6..ebc99ac 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_local.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_local.dart
@@ -22,17 +22,19 @@
   B local;
   local = /*@ typeArgs=B* */ f();
   local ??= /*@ typeArgs=B* */ f();
-  local += /*@ typeArgs=dynamic */ f();
-  local *= /*@ typeArgs=dynamic */ f();
-  local &= /*@ typeArgs=dynamic */ f();
-  --local;
-  local--;
+  local /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+  local /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+  local /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+  /*@ target=B::- */ --local;
+  local /*@ target=B::- */ --;
   var /*@ type=B* */ v1 = local = /*@ typeArgs=B* */ f();
   var /*@ type=B* */ v2 = local ??= /*@ typeArgs=B* */ f();
-  var /*@ type=B* */ v4 = local *= /*@ typeArgs=dynamic */ f();
-  var /*@ type=C* */ v5 = local &= /*@ typeArgs=dynamic */ f();
-  var /*@ type=B* */ v6 = --local;
-  var /*@ type=B* */ v7 = local--;
+  var /*@ type=A* */ v3 = local /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+  var /*@ type=B* */ v4 = local /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+  var /*@ type=C* */ v5 = local /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+  var /*@ type=B* */ v6 = /*@ target=B::- */ --local;
+  var /*@ type=B* */ v7 = /*@ type=B* */ local
+      /*@ type=B* */ /*@ target=B::- */ --;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_local.dart.strong.expect b/pkg/front_end/testcases/inference/infer_assign_to_local.dart.strong.expect
index 1762f98..35c6164 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_local.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_local.dart.strong.expect
@@ -31,15 +31,16 @@
   self::B* local;
   local = self::f<self::B*>();
   local.{core::Object::==}(null) ?{self::B*} local = self::f<self::B*>() : null;
-  local = local.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-  local = local.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  local = local.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  local = local.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  local = local.{self::B::*}(self::f<self::B*>());
+  local = local.{self::B::&}(self::f<self::A*>());
   local = local.{self::B::-}(1);
   local = local.{self::B::-}(1);
   self::B* v1 = local = self::f<self::B*>();
   self::B* v2 = let final self::B* #t1 = local in #t1.{core::Object::==}(null) ?{self::B*} local = self::f<self::B*>() : #t1;
-  self::B* v4 = local = local.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::C* v5 = local = local.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::A* v3 = local = local.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::B* v4 = local = local.{self::B::*}(self::f<self::B*>());
+  self::C* v5 = local = local.{self::B::&}(self::f<self::A*>());
   self::B* v6 = local = local.{self::B::-}(1);
   self::B* v7 = let final self::B* #t2 = local in let final self::B* #t3 = local = #t2.{self::B::-}(1) in #t2;
 }
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_local.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_local.dart.strong.transformed.expect
index 1762f98..35c6164 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_local.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_local.dart.strong.transformed.expect
@@ -31,15 +31,16 @@
   self::B* local;
   local = self::f<self::B*>();
   local.{core::Object::==}(null) ?{self::B*} local = self::f<self::B*>() : null;
-  local = local.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-  local = local.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  local = local.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  local = local.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  local = local.{self::B::*}(self::f<self::B*>());
+  local = local.{self::B::&}(self::f<self::A*>());
   local = local.{self::B::-}(1);
   local = local.{self::B::-}(1);
   self::B* v1 = local = self::f<self::B*>();
   self::B* v2 = let final self::B* #t1 = local in #t1.{core::Object::==}(null) ?{self::B*} local = self::f<self::B*>() : #t1;
-  self::B* v4 = local = local.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::C* v5 = local = local.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::A* v3 = local = local.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::B* v4 = local = local.{self::B::*}(self::f<self::B*>());
+  self::C* v5 = local = local.{self::B::&}(self::f<self::A*>());
   self::B* v6 = local = local.{self::B::-}(1);
   self::B* v7 = let final self::B* #t2 = local in let final self::B* #t3 = local = #t2.{self::B::-}(1) in #t2;
 }
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_local.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_assign_to_local.dart.type_promotion.expect
index c9be4b0..e0dc7dd 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_local.dart.type_promotion.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_local.dart.type_promotion.expect
@@ -4,36 +4,39 @@
 pkg/front_end/testcases/inference/infer_assign_to_local.dart:24:9: Context: Write to local@474
   local ??= /*@ typeArgs=B* */ f();
         ^^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:25:9: Context: Write to local@474
-  local += /*@ typeArgs=dynamic */ f();
-        ^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:26:9: Context: Write to local@474
-  local *= /*@ typeArgs=dynamic */ f();
-        ^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:27:9: Context: Write to local@474
-  local &= /*@ typeArgs=dynamic */ f();
-        ^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:28:3: Context: Write to local@474
-  --local;
-  ^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:29:8: Context: Write to local@474
-  local--;
-       ^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:25:28: Context: Write to local@474
+  local /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+                           ^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:26:28: Context: Write to local@474
+  local /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+                           ^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:27:28: Context: Write to local@474
+  local /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+                           ^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:28:22: Context: Write to local@474
+  /*@ target=B::- */ --local;
+                     ^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:29:28: Context: Write to local@474
+  local /*@ target=B::- */ --;
+                           ^^
 pkg/front_end/testcases/inference/infer_assign_to_local.dart:30:33: Context: Write to local@474
   var /*@ type=B* */ v1 = local = /*@ typeArgs=B* */ f();
                                 ^
 pkg/front_end/testcases/inference/infer_assign_to_local.dart:31:33: Context: Write to local@474
   var /*@ type=B* */ v2 = local ??= /*@ typeArgs=B* */ f();
                                 ^^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:32:33: Context: Write to local@474
-  var /*@ type=B* */ v4 = local *= /*@ typeArgs=dynamic */ f();
-                                ^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:33:33: Context: Write to local@474
-  var /*@ type=C* */ v5 = local &= /*@ typeArgs=dynamic */ f();
-                                ^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:34:27: Context: Write to local@474
-  var /*@ type=B* */ v6 = --local;
-                          ^^
-pkg/front_end/testcases/inference/infer_assign_to_local.dart:35:32: Context: Write to local@474
-  var /*@ type=B* */ v7 = local--;
-                               ^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:32:52: Context: Write to local@474
+  var /*@ type=A* */ v3 = local /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+                                                   ^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:33:52: Context: Write to local@474
+  var /*@ type=B* */ v4 = local /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+                                                   ^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:34:52: Context: Write to local@474
+  var /*@ type=C* */ v5 = local /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+                                                   ^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:35:46: Context: Write to local@474
+  var /*@ type=B* */ v6 = /*@ target=B::- */ --local;
+                                             ^^
+pkg/front_end/testcases/inference/infer_assign_to_local.dart:37:41: Context: Write to local@474
+      /*@ type=B* */ /*@ target=B::- */ --;
+                                        ^^
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart b/pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart
index 98ac8ac..fef536a 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart
@@ -12,9 +12,9 @@
 void test1(int t) {
   var /*@ type=int* */ v1 = t = getInt();
   var /*@ type=int* */ v4 = t ??= getInt();
-  var /*@ type=int* */ v7 = t += getInt();
-  var /*@ type=int* */ v10 = ++t;
-  var /*@ type=int* */ v11 = t++;
+  var /*@ type=int* */ v7 = t /*@target=num::+*/ += getInt();
+  var /*@ type=int* */ v10 = /*@target=num::+*/ ++t;
+  var /*@ type=int* */ v11 = /*@ type=int* */ t /*@ type=int* */ /*@target=num::+*/ ++;
 }
 
 void test2(num t) {
@@ -24,21 +24,22 @@
   var /*@ type=num* */ v4 = t ??= getInt();
   var /*@ type=num* */ v5 = t ??= getNum();
   var /*@ type=num* */ v6 = t ??= getDouble();
-  var /*@ type=num* */ v7 = t += getInt();
-  var /*@ type=num* */ v8 = t += getNum();
-  var /*@ type=num* */ v9 = t += getDouble();
-  var /*@ type=num* */ v10 = ++t;
-  var /*@ type=num* */ v11 = t++;
+  var /*@ type=num* */ v7 = t /*@target=num::+*/ += getInt();
+  var /*@ type=num* */ v8 = t /*@target=num::+*/ += getNum();
+  var /*@ type=num* */ v9 = t /*@target=num::+*/ += getDouble();
+  var /*@ type=num* */ v10 = /*@target=num::+*/ ++t;
+  var /*@ type=num* */ v11 = /*@ type=num* */ t /*@ type=num* */ /*@target=num::+*/ ++;
 }
 
 void test3(double t) {
   var /*@ type=double* */ v3 = t = getDouble();
   var /*@ type=double* */ v6 = t ??= getDouble();
-  var /*@ type=double* */ v7 = t += getInt();
-  var /*@ type=double* */ v8 = t += getNum();
-  var /*@ type=double* */ v9 = t += getDouble();
-  var /*@ type=double* */ v10 = ++t;
-  var /*@ type=double* */ v11 = t++;
+  var /*@ type=double* */ v7 = t /*@target=double::+*/ += getInt();
+  var /*@ type=double* */ v8 = t /*@target=double::+*/ += getNum();
+  var /*@ type=double* */ v9 = t /*@target=double::+*/ += getDouble();
+  var /*@ type=double* */ v10 = /*@target=double::+*/ ++t;
+  var /*@ type=double* */ v11 = /*@ type=double* */ t
+      /*@ type=double* */ /*@target=double::+*/ ++;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart.type_promotion.expect
index e3a6044..80ef25c 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart.type_promotion.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart.type_promotion.expect
@@ -4,15 +4,15 @@
 pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:14:31: Context: Write to t@343
   var /*@ type=int* */ v4 = t ??= getInt();
                               ^^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:15:31: Context: Write to t@343
-  var /*@ type=int* */ v7 = t += getInt();
-                              ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:16:30: Context: Write to t@343
-  var /*@ type=int* */ v10 = ++t;
-                             ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:17:31: Context: Write to t@343
-  var /*@ type=int* */ v11 = t++;
-                              ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:15:50: Context: Write to t@343
+  var /*@ type=int* */ v7 = t /*@target=num::+*/ += getInt();
+                                                 ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:16:49: Context: Write to t@343
+  var /*@ type=int* */ v10 = /*@target=num::+*/ ++t;
+                                                ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:17:85: Context: Write to t@343
+  var /*@ type=int* */ v11 = /*@ type=int* */ t /*@ type=int* */ /*@target=num::+*/ ++;
+                                                                                    ^^
 pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:21:31: Context: Write to t@343
   var /*@ type=int* */ v1 = t = getInt();
                               ^
@@ -31,39 +31,39 @@
 pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:26:31: Context: Write to t@343
   var /*@ type=num* */ v6 = t ??= getDouble();
                               ^^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:27:31: Context: Write to t@343
-  var /*@ type=num* */ v7 = t += getInt();
-                              ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:28:31: Context: Write to t@343
-  var /*@ type=num* */ v8 = t += getNum();
-                              ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:29:31: Context: Write to t@343
-  var /*@ type=num* */ v9 = t += getDouble();
-                              ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:30:30: Context: Write to t@343
-  var /*@ type=num* */ v10 = ++t;
-                             ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:31:31: Context: Write to t@343
-  var /*@ type=num* */ v11 = t++;
-                              ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:27:50: Context: Write to t@343
+  var /*@ type=num* */ v7 = t /*@target=num::+*/ += getInt();
+                                                 ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:28:50: Context: Write to t@343
+  var /*@ type=num* */ v8 = t /*@target=num::+*/ += getNum();
+                                                 ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:29:50: Context: Write to t@343
+  var /*@ type=num* */ v9 = t /*@target=num::+*/ += getDouble();
+                                                 ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:30:49: Context: Write to t@343
+  var /*@ type=num* */ v10 = /*@target=num::+*/ ++t;
+                                                ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:31:85: Context: Write to t@343
+  var /*@ type=num* */ v11 = /*@ type=num* */ t /*@ type=num* */ /*@target=num::+*/ ++;
+                                                                                    ^^
 pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:35:34: Context: Write to t@343
   var /*@ type=double* */ v3 = t = getDouble();
                                  ^
 pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:36:34: Context: Write to t@343
   var /*@ type=double* */ v6 = t ??= getDouble();
                                  ^^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:37:34: Context: Write to t@343
-  var /*@ type=double* */ v7 = t += getInt();
-                                 ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:38:34: Context: Write to t@343
-  var /*@ type=double* */ v8 = t += getNum();
-                                 ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:39:34: Context: Write to t@343
-  var /*@ type=double* */ v9 = t += getDouble();
-                                 ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:40:33: Context: Write to t@343
-  var /*@ type=double* */ v10 = ++t;
-                                ^^
-pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:41:34: Context: Write to t@343
-  var /*@ type=double* */ v11 = t++;
-                                 ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:37:56: Context: Write to t@343
+  var /*@ type=double* */ v7 = t /*@target=double::+*/ += getInt();
+                                                       ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:38:56: Context: Write to t@343
+  var /*@ type=double* */ v8 = t /*@target=double::+*/ += getNum();
+                                                       ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:39:56: Context: Write to t@343
+  var /*@ type=double* */ v9 = t /*@target=double::+*/ += getDouble();
+                                                       ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:40:55: Context: Write to t@343
+  var /*@ type=double* */ v10 = /*@target=double::+*/ ++t;
+                                                      ^^
+pkg/front_end/testcases/inference/infer_assign_to_local_upwards.dart:42:49: Context: Write to t@343
+      /*@ type=double* */ /*@target=double::+*/ ++;
+                                                ^^
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart b/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart
index b3bffe0..0fc74d0 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart
@@ -23,22 +23,46 @@
 
   static void test(Test t) {
     t. /*@target=Test::member*/ member = /*@ typeArgs=B* */ f();
-    t. /*@target=Test::member*/ member ??= /*@ typeArgs=B* */ f();
-    t. /*@target=Test::member*/ member += /*@ typeArgs=dynamic */ f();
-    t. /*@target=Test::member*/ member *= /*@ typeArgs=dynamic */ f();
-    t. /*@target=Test::member*/ member &= /*@ typeArgs=dynamic */ f();
-    --t. /*@target=Test::member*/ member;
-    t. /*@target=Test::member*/ member--;
+    /*@ type=Test* */ t
+            . /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@target=Object::==*/ ??= /*@ typeArgs=B* */ f();
+    /*@ type=Test* */ t
+            . /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+    /*@ type=Test* */ t
+            . /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+    /*@ type=Test* */ t
+            . /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+    /*@ target=B::- */ -- /*@ type=Test* */ t
+        . /*@target=Test::member*/ /*@target=Test::member*/ member;
+    /*@ type=Test* */ t
+            . /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::- */ --;
     var /*@ type=B* */ v1 =
         t. /*@target=Test::member*/ member = /*@ typeArgs=B* */ f();
     var /*@ type=B* */ v2 =
-        t. /*@target=Test::member*/ member ??= /*@ typeArgs=B* */ f();
+        /*@ type=Test* */ t
+                . /*@target=Test::member*/ /*@target=Test::member*/ member
+            /*@target=Object::==*/ ??= /*@ typeArgs=B* */ f();
+    var /*@ type=A* */ v3 =
+        /*@ type=Test* */ t
+                . /*@target=Test::member*/ /*@target=Test::member*/ member
+            /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
     var /*@ type=B* */ v4 =
-        t. /*@target=Test::member*/ member *= /*@ typeArgs=dynamic */ f();
+        /*@ type=Test* */ t
+                . /*@target=Test::member*/ /*@target=Test::member*/ member
+            /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
     var /*@ type=C* */ v5 =
-        t. /*@target=Test::member*/ member &= /*@ typeArgs=dynamic */ f();
-    var /*@ type=B* */ v6 = --t. /*@target=Test::member*/ member;
-    var /*@ type=B* */ v7 = t. /*@target=Test::member*/ member--;
+        /*@ type=Test* */ t
+                . /*@target=Test::member*/ /*@target=Test::member*/ member
+            /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+    var /*@ type=B* */ v6 = /*@ target=B::- */ -- /*@ type=Test* */ t
+        . /*@target=Test::member*/ /*@target=Test::member*/ member;
+    var /*@ type=B* */ v7 = /*@ type=Test* */ t
+        . /*@ type=B* */ /*@target=Test::member*/ /*@target=Test::member*/
+        member /*@ type=B* */ /*@ target=B::- */ --;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart.strong.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart.strong.expect
index def1efc..5809936 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart.strong.expect
@@ -33,17 +33,18 @@
   static method test(self::Test* t) → void {
     t.{self::Test::member} = self::f<self::B*>();
     let final self::Test* #t1 = t in #t1.{self::Test::member}.{core::Object::==}(null) ?{self::B*} #t1.{self::Test::member} = self::f<self::B*>() : null;
-    let final self::Test* #t2 = t in #t2.{self::Test::member} = #t2.{self::Test::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-    let final self::Test* #t3 = t in #t3.{self::Test::member} = #t3.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    let final self::Test* #t4 = t in #t4.{self::Test::member} = #t4.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    let final self::Test* #t2 = t in #t2.{self::Test::member} = #t2.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    let final self::Test* #t3 = t in #t3.{self::Test::member} = #t3.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    let final self::Test* #t4 = t in #t4.{self::Test::member} = #t4.{self::Test::member}.{self::B::&}(self::f<self::A*>());
     let final self::Test* #t5 = t in #t5.{self::Test::member} = #t5.{self::Test::member}.{self::B::-}(1);
     let final self::Test* #t6 = t in #t6.{self::Test::member} = #t6.{self::Test::member}.{self::B::-}(1);
     self::B* v1 = t.{self::Test::member} = self::f<self::B*>();
     self::B* v2 = let final self::Test* #t7 = t in let final self::B* #t8 = #t7.{self::Test::member} in #t8.{core::Object::==}(null) ?{self::B*} #t7.{self::Test::member} = self::f<self::B*>() : #t8;
-    self::B* v4 = let final self::Test* #t9 = t in #t9.{self::Test::member} = #t9.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    self::C* v5 = let final self::Test* #t10 = t in #t10.{self::Test::member} = #t10.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
-    self::B* v6 = let final self::Test* #t11 = t in #t11.{self::Test::member} = #t11.{self::Test::member}.{self::B::-}(1);
-    self::B* v7 = let final self::Test* #t12 = t in let final self::B* #t13 = #t12.{self::Test::member} in let final self::B* #t14 = #t12.{self::Test::member} = #t13.{self::B::-}(1) in #t13;
+    self::A* v3 = let final self::Test* #t9 = t in #t9.{self::Test::member} = #t9.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    self::B* v4 = let final self::Test* #t10 = t in #t10.{self::Test::member} = #t10.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    self::C* v5 = let final self::Test* #t11 = t in #t11.{self::Test::member} = #t11.{self::Test::member}.{self::B::&}(self::f<self::A*>());
+    self::B* v6 = let final self::Test* #t12 = t in #t12.{self::Test::member} = #t12.{self::Test::member}.{self::B::-}(1);
+    self::B* v7 = let final self::Test* #t13 = t in let final self::B* #t14 = #t13.{self::Test::member} in let final self::B* #t15 = #t13.{self::Test::member} = #t14.{self::B::-}(1) in #t14;
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart.strong.transformed.expect
index def1efc..5809936 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart.strong.transformed.expect
@@ -33,17 +33,18 @@
   static method test(self::Test* t) → void {
     t.{self::Test::member} = self::f<self::B*>();
     let final self::Test* #t1 = t in #t1.{self::Test::member}.{core::Object::==}(null) ?{self::B*} #t1.{self::Test::member} = self::f<self::B*>() : null;
-    let final self::Test* #t2 = t in #t2.{self::Test::member} = #t2.{self::Test::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-    let final self::Test* #t3 = t in #t3.{self::Test::member} = #t3.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    let final self::Test* #t4 = t in #t4.{self::Test::member} = #t4.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    let final self::Test* #t2 = t in #t2.{self::Test::member} = #t2.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    let final self::Test* #t3 = t in #t3.{self::Test::member} = #t3.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    let final self::Test* #t4 = t in #t4.{self::Test::member} = #t4.{self::Test::member}.{self::B::&}(self::f<self::A*>());
     let final self::Test* #t5 = t in #t5.{self::Test::member} = #t5.{self::Test::member}.{self::B::-}(1);
     let final self::Test* #t6 = t in #t6.{self::Test::member} = #t6.{self::Test::member}.{self::B::-}(1);
     self::B* v1 = t.{self::Test::member} = self::f<self::B*>();
     self::B* v2 = let final self::Test* #t7 = t in let final self::B* #t8 = #t7.{self::Test::member} in #t8.{core::Object::==}(null) ?{self::B*} #t7.{self::Test::member} = self::f<self::B*>() : #t8;
-    self::B* v4 = let final self::Test* #t9 = t in #t9.{self::Test::member} = #t9.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    self::C* v5 = let final self::Test* #t10 = t in #t10.{self::Test::member} = #t10.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
-    self::B* v6 = let final self::Test* #t11 = t in #t11.{self::Test::member} = #t11.{self::Test::member}.{self::B::-}(1);
-    self::B* v7 = let final self::Test* #t12 = t in let final self::B* #t13 = #t12.{self::Test::member} in let final self::B* #t14 = #t12.{self::Test::member} = #t13.{self::B::-}(1) in #t13;
+    self::A* v3 = let final self::Test* #t9 = t in #t9.{self::Test::member} = #t9.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    self::B* v4 = let final self::Test* #t10 = t in #t10.{self::Test::member} = #t10.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    self::C* v5 = let final self::Test* #t11 = t in #t11.{self::Test::member} = #t11.{self::Test::member}.{self::B::&}(self::f<self::A*>());
+    self::B* v6 = let final self::Test* #t12 = t in #t12.{self::Test::member} = #t12.{self::Test::member}.{self::B::-}(1);
+    self::B* v7 = let final self::Test* #t13 = t in let final self::B* #t14 = #t13.{self::Test::member} in let final self::B* #t15 = #t13.{self::Test::member} = #t14.{self::B::-}(1) in #t14;
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart b/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart
index 3c0dfaa..55d9fb1 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart
@@ -22,7 +22,8 @@
   B member;
 
   static void test(Test t) {
-    t?. /*@target=Test::member*/ member = /*@ typeArgs=B* */ f();
+    /*@ type=Test* */ /*@target=Object::==*/ t?. /*@target=Test::member*/
+        member = /*@ typeArgs=B* */ f();
     t?. /*@target=Test::member*/ member ??= /*@ typeArgs=B* */ f();
     t?. /*@target=Test::member*/ member += /*@ typeArgs=dynamic */ f();
     t?. /*@target=Test::member*/ member *= /*@ typeArgs=dynamic */ f();
@@ -30,7 +31,8 @@
     --t?. /*@target=Test::member*/ member;
     t?. /*@target=Test::member*/ member--;
     var /*@ type=B* */ v1 =
-        t?. /*@target=Test::member*/ member = /*@ typeArgs=B* */ f();
+        /*@ type=Test* */ /*@target=Object::==*/ t?. /*@target=Test::member*/
+            member = /*@ typeArgs=B* */ f();
     var /*@ type=B* */ v2 =
         t?. /*@target=Test::member*/ member ??= /*@ typeArgs=B* */ f();
     var /*@ type=B* */ v4 =
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart.strong.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart.strong.expect
index 1a893e5..6c00bcb4 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart.strong.expect
@@ -31,14 +31,14 @@
     : super core::Object::•()
     ;
   static method test(self::Test* t) → void {
-    let final self::Test* #t1 = t in #t1.==(null) ?{self::B*} null : #t1.{self::Test::member} = self::f<self::B*>();
+    let final self::Test* #t1 = t in #t1.{core::Object::==}(null) ?{self::B*} null : #t1.{self::Test::member} = self::f<self::B*>();
     let final self::Test* #t2 = t in #t2.==(null) ?{self::B*} null : #t2.{self::Test::member}.{core::Object::==}(null) ?{self::B*} #t2.{self::Test::member} = self::f<self::B*>() : null;
     let final self::Test* #t3 = t in #t3.==(null) ?{self::A*} null : #t3.{self::Test::member} = #t3.{self::Test::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
     let final self::Test* #t4 = t in #t4.==(null) ?{self::B*} null : #t4.{self::Test::member} = #t4.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
     let final self::Test* #t5 = t in #t5.==(null) ?{self::C*} null : #t5.{self::Test::member} = #t5.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
     let final self::Test* #t6 = t in #t6.==(null) ?{self::B*} null : #t6.{self::Test::member} = #t6.{self::Test::member}.{self::B::-}(1);
     let final self::Test* #t7 = t in #t7.==(null) ?{self::B*} null : #t7.{self::Test::member} = #t7.{self::Test::member}.{self::B::-}(1);
-    self::B* v1 = let final self::Test* #t8 = t in #t8.==(null) ?{self::B*} null : #t8.{self::Test::member} = self::f<self::B*>();
+    self::B* v1 = let final self::Test* #t8 = t in #t8.{core::Object::==}(null) ?{self::B*} null : #t8.{self::Test::member} = self::f<self::B*>();
     self::B* v2 = let final self::Test* #t9 = t in #t9.==(null) ?{self::B*} null : let final self::B* #t10 = #t9.{self::Test::member} in #t10.{core::Object::==}(null) ?{self::B*} #t9.{self::Test::member} = self::f<self::B*>() : #t10;
     self::B* v4 = let final self::Test* #t11 = t in #t11.==(null) ?{self::B*} null : #t11.{self::Test::member} = #t11.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
     self::C* v5 = let final self::Test* #t12 = t in #t12.==(null) ?{self::C*} null : #t12.{self::Test::member} = #t12.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart.strong.transformed.expect
index 1a893e5..6c00bcb4 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware.dart.strong.transformed.expect
@@ -31,14 +31,14 @@
     : super core::Object::•()
     ;
   static method test(self::Test* t) → void {
-    let final self::Test* #t1 = t in #t1.==(null) ?{self::B*} null : #t1.{self::Test::member} = self::f<self::B*>();
+    let final self::Test* #t1 = t in #t1.{core::Object::==}(null) ?{self::B*} null : #t1.{self::Test::member} = self::f<self::B*>();
     let final self::Test* #t2 = t in #t2.==(null) ?{self::B*} null : #t2.{self::Test::member}.{core::Object::==}(null) ?{self::B*} #t2.{self::Test::member} = self::f<self::B*>() : null;
     let final self::Test* #t3 = t in #t3.==(null) ?{self::A*} null : #t3.{self::Test::member} = #t3.{self::Test::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
     let final self::Test* #t4 = t in #t4.==(null) ?{self::B*} null : #t4.{self::Test::member} = #t4.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
     let final self::Test* #t5 = t in #t5.==(null) ?{self::C*} null : #t5.{self::Test::member} = #t5.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
     let final self::Test* #t6 = t in #t6.==(null) ?{self::B*} null : #t6.{self::Test::member} = #t6.{self::Test::member}.{self::B::-}(1);
     let final self::Test* #t7 = t in #t7.==(null) ?{self::B*} null : #t7.{self::Test::member} = #t7.{self::Test::member}.{self::B::-}(1);
-    self::B* v1 = let final self::Test* #t8 = t in #t8.==(null) ?{self::B*} null : #t8.{self::Test::member} = self::f<self::B*>();
+    self::B* v1 = let final self::Test* #t8 = t in #t8.{core::Object::==}(null) ?{self::B*} null : #t8.{self::Test::member} = self::f<self::B*>();
     self::B* v2 = let final self::Test* #t9 = t in #t9.==(null) ?{self::B*} null : let final self::B* #t10 = #t9.{self::Test::member} in #t10.{core::Object::==}(null) ?{self::B*} #t9.{self::Test::member} = self::f<self::B*>() : #t10;
     self::B* v4 = let final self::Test* #t11 = t in #t11.==(null) ?{self::B*} null : #t11.{self::Test::member} = #t11.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
     self::C* v5 = let final self::Test* #t12 = t in #t12.==(null) ?{self::C*} null : #t12.{self::Test::member} = #t12.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart b/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart
index e245dfe..eab5036 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart
@@ -13,7 +13,8 @@
   int prop;
 
   static void test(Test1 t) {
-    var /*@ type=int* */ v1 = t?. /*@target=Test1::prop*/ prop = getInt();
+    var /*@ type=int* */ v1 = /*@ type=Test1* */ /*@target=Object::==*/ t
+        ?. /*@target=Test1::prop*/ prop = getInt();
     var /*@ type=int* */ v4 = t?. /*@target=Test1::prop*/ prop ??= getInt();
     var /*@ type=int* */ v7 = t?. /*@target=Test1::prop*/ prop += getInt();
     var /*@ type=int* */ v10 = ++t?. /*@target=Test1::prop*/ prop;
@@ -25,9 +26,12 @@
   num prop;
 
   static void test(Test2 t) {
-    var /*@ type=int* */ v1 = t?. /*@target=Test2::prop*/ prop = getInt();
-    var /*@ type=num* */ v2 = t?. /*@target=Test2::prop*/ prop = getNum();
-    var /*@ type=double* */ v3 = t?. /*@target=Test2::prop*/ prop = getDouble();
+    var /*@ type=int* */ v1 = /*@ type=Test2* */ /*@target=Object::==*/ t
+        ?. /*@target=Test2::prop*/ prop = getInt();
+    var /*@ type=num* */ v2 = /*@ type=Test2* */ /*@target=Object::==*/ t
+        ?. /*@target=Test2::prop*/ prop = getNum();
+    var /*@ type=double* */ v3 = /*@ type=Test2* */ /*@target=Object::==*/ t
+        ?. /*@target=Test2::prop*/ prop = getDouble();
     var /*@ type=num* */ v4 = t?. /*@target=Test2::prop*/ prop ??= getInt();
     var /*@ type=num* */ v5 = t?. /*@target=Test2::prop*/ prop ??= getNum();
     var /*@ type=num* */ v6 = t?. /*@target=Test2::prop*/ prop ??= getDouble();
@@ -43,11 +47,15 @@
   double prop;
 
   static void test3(Test3 t) {
-    var /*@ type=double* */ v3 = t?. /*@target=Test3::prop*/ prop = getDouble();
-    var /*@ type=double* */ v6 = t?. /*@target=Test3::prop*/ prop ??= getDouble();
+    var /*@ type=double* */ v3 =
+        /*@ type=Test3* */ /*@target=Object::==*/ t
+            ?. /*@target=Test3::prop*/ prop = getDouble();
+    var /*@ type=double* */ v6 =
+        t?. /*@target=Test3::prop*/ prop ??= getDouble();
     var /*@ type=double* */ v7 = t?. /*@target=Test3::prop*/ prop += getInt();
     var /*@ type=double* */ v8 = t?. /*@target=Test3::prop*/ prop += getNum();
-    var /*@ type=double* */ v9 = t?. /*@target=Test3::prop*/ prop += getDouble();
+    var /*@ type=double* */ v9 =
+        t?. /*@target=Test3::prop*/ prop += getDouble();
     var /*@ type=double* */ v10 = ++t?. /*@target=Test3::prop*/ prop;
     var /*@ type=double* */ v11 = t?. /*@target=Test3::prop*/ prop++;
   }
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart.strong.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart.strong.expect
index 2b996bb..891b1bd 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart.strong.expect
@@ -8,7 +8,7 @@
     : super core::Object::•()
     ;
   static method test(self::Test1* t) → void {
-    core::int* v1 = let final self::Test1* #t1 = t in #t1.==(null) ?{core::int*} null : #t1.{self::Test1::prop} = self::getInt();
+    core::int* v1 = let final self::Test1* #t1 = t in #t1.{core::Object::==}(null) ?{core::int*} null : #t1.{self::Test1::prop} = self::getInt();
     core::int* v4 = let final self::Test1* #t2 = t in #t2.==(null) ?{core::int*} null : let final core::int* #t3 = #t2.{self::Test1::prop} in #t3.{core::num::==}(null) ?{core::int*} #t2.{self::Test1::prop} = self::getInt() : #t3;
     core::int* v7 = let final self::Test1* #t4 = t in #t4.==(null) ?{core::int*} null : #t4.{self::Test1::prop} = #t4.{self::Test1::prop}.{core::num::+}(self::getInt());
     core::int* v10 = let final self::Test1* #t5 = t in #t5.==(null) ?{core::int*} null : #t5.{self::Test1::prop} = #t5.{self::Test1::prop}.{core::num::+}(1);
@@ -21,9 +21,9 @@
     : super core::Object::•()
     ;
   static method test(self::Test2* t) → void {
-    core::int* v1 = let final self::Test2* #t9 = t in #t9.==(null) ?{core::int*} null : #t9.{self::Test2::prop} = self::getInt();
-    core::num* v2 = let final self::Test2* #t10 = t in #t10.==(null) ?{core::num*} null : #t10.{self::Test2::prop} = self::getNum();
-    core::double* v3 = let final self::Test2* #t11 = t in #t11.==(null) ?{core::double*} null : #t11.{self::Test2::prop} = self::getDouble();
+    core::int* v1 = let final self::Test2* #t9 = t in #t9.{core::Object::==}(null) ?{core::int*} null : #t9.{self::Test2::prop} = self::getInt();
+    core::num* v2 = let final self::Test2* #t10 = t in #t10.{core::Object::==}(null) ?{core::num*} null : #t10.{self::Test2::prop} = self::getNum();
+    core::double* v3 = let final self::Test2* #t11 = t in #t11.{core::Object::==}(null) ?{core::double*} null : #t11.{self::Test2::prop} = self::getDouble();
     core::num* v4 = let final self::Test2* #t12 = t in #t12.==(null) ?{core::num*} null : let final core::num* #t13 = #t12.{self::Test2::prop} in #t13.{core::num::==}(null) ?{core::num*} #t12.{self::Test2::prop} = self::getInt() : #t13;
     core::num* v5 = let final self::Test2* #t14 = t in #t14.==(null) ?{core::num*} null : let final core::num* #t15 = #t14.{self::Test2::prop} in #t15.{core::num::==}(null) ?{core::num*} #t14.{self::Test2::prop} = self::getNum() : #t15;
     core::num* v6 = let final self::Test2* #t16 = t in #t16.==(null) ?{core::num*} null : let final core::num* #t17 = #t16.{self::Test2::prop} in #t17.{core::num::==}(null) ?{core::num*} #t16.{self::Test2::prop} = self::getDouble() : #t17;
@@ -40,7 +40,7 @@
     : super core::Object::•()
     ;
   static method test3(self::Test3* t) → void {
-    core::double* v3 = let final self::Test3* #t25 = t in #t25.==(null) ?{core::double*} null : #t25.{self::Test3::prop} = self::getDouble();
+    core::double* v3 = let final self::Test3* #t25 = t in #t25.{core::Object::==}(null) ?{core::double*} null : #t25.{self::Test3::prop} = self::getDouble();
     core::double* v6 = let final self::Test3* #t26 = t in #t26.==(null) ?{core::double*} null : let final core::double* #t27 = #t26.{self::Test3::prop} in #t27.{core::num::==}(null) ?{core::double*} #t26.{self::Test3::prop} = self::getDouble() : #t27;
     core::double* v7 = let final self::Test3* #t28 = t in #t28.==(null) ?{core::double*} null : #t28.{self::Test3::prop} = #t28.{self::Test3::prop}.{core::double::+}(self::getInt());
     core::double* v8 = let final self::Test3* #t29 = t in #t29.==(null) ?{core::double*} null : #t29.{self::Test3::prop} = #t29.{self::Test3::prop}.{core::double::+}(self::getNum());
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart.strong.transformed.expect
index 2b996bb..891b1bd 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_property_null_aware_upwards.dart.strong.transformed.expect
@@ -8,7 +8,7 @@
     : super core::Object::•()
     ;
   static method test(self::Test1* t) → void {
-    core::int* v1 = let final self::Test1* #t1 = t in #t1.==(null) ?{core::int*} null : #t1.{self::Test1::prop} = self::getInt();
+    core::int* v1 = let final self::Test1* #t1 = t in #t1.{core::Object::==}(null) ?{core::int*} null : #t1.{self::Test1::prop} = self::getInt();
     core::int* v4 = let final self::Test1* #t2 = t in #t2.==(null) ?{core::int*} null : let final core::int* #t3 = #t2.{self::Test1::prop} in #t3.{core::num::==}(null) ?{core::int*} #t2.{self::Test1::prop} = self::getInt() : #t3;
     core::int* v7 = let final self::Test1* #t4 = t in #t4.==(null) ?{core::int*} null : #t4.{self::Test1::prop} = #t4.{self::Test1::prop}.{core::num::+}(self::getInt());
     core::int* v10 = let final self::Test1* #t5 = t in #t5.==(null) ?{core::int*} null : #t5.{self::Test1::prop} = #t5.{self::Test1::prop}.{core::num::+}(1);
@@ -21,9 +21,9 @@
     : super core::Object::•()
     ;
   static method test(self::Test2* t) → void {
-    core::int* v1 = let final self::Test2* #t9 = t in #t9.==(null) ?{core::int*} null : #t9.{self::Test2::prop} = self::getInt();
-    core::num* v2 = let final self::Test2* #t10 = t in #t10.==(null) ?{core::num*} null : #t10.{self::Test2::prop} = self::getNum();
-    core::double* v3 = let final self::Test2* #t11 = t in #t11.==(null) ?{core::double*} null : #t11.{self::Test2::prop} = self::getDouble();
+    core::int* v1 = let final self::Test2* #t9 = t in #t9.{core::Object::==}(null) ?{core::int*} null : #t9.{self::Test2::prop} = self::getInt();
+    core::num* v2 = let final self::Test2* #t10 = t in #t10.{core::Object::==}(null) ?{core::num*} null : #t10.{self::Test2::prop} = self::getNum();
+    core::double* v3 = let final self::Test2* #t11 = t in #t11.{core::Object::==}(null) ?{core::double*} null : #t11.{self::Test2::prop} = self::getDouble();
     core::num* v4 = let final self::Test2* #t12 = t in #t12.==(null) ?{core::num*} null : let final core::num* #t13 = #t12.{self::Test2::prop} in #t13.{core::num::==}(null) ?{core::num*} #t12.{self::Test2::prop} = self::getInt() : #t13;
     core::num* v5 = let final self::Test2* #t14 = t in #t14.==(null) ?{core::num*} null : let final core::num* #t15 = #t14.{self::Test2::prop} in #t15.{core::num::==}(null) ?{core::num*} #t14.{self::Test2::prop} = self::getNum() : #t15;
     core::num* v6 = let final self::Test2* #t16 = t in #t16.==(null) ?{core::num*} null : let final core::num* #t17 = #t16.{self::Test2::prop} in #t17.{core::num::==}(null) ?{core::num*} #t16.{self::Test2::prop} = self::getDouble() : #t17;
@@ -40,7 +40,7 @@
     : super core::Object::•()
     ;
   static method test3(self::Test3* t) → void {
-    core::double* v3 = let final self::Test3* #t25 = t in #t25.==(null) ?{core::double*} null : #t25.{self::Test3::prop} = self::getDouble();
+    core::double* v3 = let final self::Test3* #t25 = t in #t25.{core::Object::==}(null) ?{core::double*} null : #t25.{self::Test3::prop} = self::getDouble();
     core::double* v6 = let final self::Test3* #t26 = t in #t26.==(null) ?{core::double*} null : let final core::double* #t27 = #t26.{self::Test3::prop} in #t27.{core::num::==}(null) ?{core::double*} #t26.{self::Test3::prop} = self::getDouble() : #t27;
     core::double* v7 = let final self::Test3* #t28 = t in #t28.==(null) ?{core::double*} null : #t28.{self::Test3::prop} = #t28.{self::Test3::prop}.{core::double::+}(self::getInt());
     core::double* v8 = let final self::Test3* #t29 = t in #t29.==(null) ?{core::double*} null : #t29.{self::Test3::prop} = #t29.{self::Test3::prop}.{core::double::+}(self::getNum());
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart b/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart
index 2982026..26313de 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart
@@ -25,22 +25,52 @@
 class Test extends Base {
   void test() {
     super. /*@target=Base::member*/ member = /*@ typeArgs=B* */ f();
-    super. /*@target=Base::member*/ member ??= /*@ typeArgs=B* */ f();
-    super. /*@target=Base::member*/ member += /*@ typeArgs=dynamic */ f();
-    super. /*@target=Base::member*/ member *= /*@ typeArgs=dynamic */ f();
-    super. /*@target=Base::member*/ member &= /*@ typeArgs=dynamic */ f();
-    --super. /*@target=Base::member*/ member;
-    super. /*@target=Base::member*/ member--;
+
+    super. /*@target=Base::member*/ /*@target=Base::member*/ member
+        /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
+    super. /*@target=Base::member*/ /*@target=Base::member*/ member
+        /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+    super. /*@target=Base::member*/ /*@target=Base::member*/ member
+        /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+    super. /*@target=Base::member*/ /*@target=Base::member*/ member
+        /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+    /*@ target=B::- */ --super
+        . /*@target=Base::member*/ /*@target=Base::member*/ member;
+
+    super. /*@target=Base::member*/ /*@target=Base::member*/ member
+        /*@ target=B::- */ --;
+
     var /*@ type=B* */ v1 =
         super. /*@target=Base::member*/ member = /*@ typeArgs=B* */ f();
+
     var /*@ type=B* */ v2 =
-        super. /*@target=Base::member*/ member ??= /*@ typeArgs=B* */ f();
+        super. /*@target=Base::member*/ /*@target=Base::member*/ member
+            /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
+    var /*@ type=A* */ v3 =
+        super. /*@target=Base::member*/ /*@target=Base::member*/ member
+            /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
     var /*@ type=B* */ v4 =
-        super. /*@target=Base::member*/ member *= /*@ typeArgs=dynamic */ f();
+        super. /*@target=Base::member*/ /*@target=Base::member*/ member
+            /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
     var /*@ type=C* */ v5 =
-        super. /*@target=Base::member*/ member &= /*@ typeArgs=dynamic */ f();
-    var /*@ type=B* */ v6 = --super. /*@target=Base::member*/ member;
-    var /*@ type=B* */ v7 = super. /*@target=Base::member*/ member--;
+        super. /*@target=Base::member*/ /*@target=Base::member*/ member
+            /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+    var /*@ type=B* */ v6 =
+        /*@ target=B::- */ --super
+            . /*@target=Base::member*/ /*@target=Base::member*/ member;
+
+    var /*@ type=B* */ v7 = super
+            . /*@ type=B* */ /*@target=Base::member*/ /*@target=Base::member*/
+            member
+        /*@ type=B* */ /*@ target=B::- */ --;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart.strong.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart.strong.expect
index 50d58e2..eb317ce 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart.strong.expect
@@ -38,15 +38,16 @@
   method test() → void {
     super.{self::Base::member} = self::f<self::B*>();
     super.{self::Base::member}.{core::Object::==}(null) ?{self::B*} super.{self::Base::member} = self::f<self::B*>() : null;
-    super.{self::Base::member} = super.{self::Base::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-    super.{self::Base::member} = super.{self::Base::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    super.{self::Base::member} = super.{self::Base::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    super.{self::Base::member} = super.{self::Base::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    super.{self::Base::member} = super.{self::Base::member}.{self::B::*}(self::f<self::B*>());
+    super.{self::Base::member} = super.{self::Base::member}.{self::B::&}(self::f<self::A*>());
     super.{self::Base::member} = super.{self::Base::member}.{self::B::-}(1);
     super.{self::Base::member} = super.{self::Base::member}.{self::B::-}(1);
     self::B* v1 = super.{self::Base::member} = self::f<self::B*>();
     self::B* v2 = let final self::B* #t1 = super.{self::Base::member} in #t1.{core::Object::==}(null) ?{self::B*} super.{self::Base::member} = self::f<self::B*>() : #t1;
-    self::B* v4 = super.{self::Base::member} = super.{self::Base::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    self::C* v5 = super.{self::Base::member} = super.{self::Base::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    self::A* v3 = super.{self::Base::member} = super.{self::Base::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    self::B* v4 = super.{self::Base::member} = super.{self::Base::member}.{self::B::*}(self::f<self::B*>());
+    self::C* v5 = super.{self::Base::member} = super.{self::Base::member}.{self::B::&}(self::f<self::A*>());
     self::B* v6 = super.{self::Base::member} = super.{self::Base::member}.{self::B::-}(1);
     self::B* v7 = let final self::B* #t2 = super.{self::Base::member} in let final self::B* #t3 = super.{self::Base::member} = #t2.{self::B::-}(1) in #t2;
   }
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart.strong.transformed.expect
index 50d58e2..eb317ce 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart.strong.transformed.expect
@@ -38,15 +38,16 @@
   method test() → void {
     super.{self::Base::member} = self::f<self::B*>();
     super.{self::Base::member}.{core::Object::==}(null) ?{self::B*} super.{self::Base::member} = self::f<self::B*>() : null;
-    super.{self::Base::member} = super.{self::Base::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-    super.{self::Base::member} = super.{self::Base::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    super.{self::Base::member} = super.{self::Base::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    super.{self::Base::member} = super.{self::Base::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    super.{self::Base::member} = super.{self::Base::member}.{self::B::*}(self::f<self::B*>());
+    super.{self::Base::member} = super.{self::Base::member}.{self::B::&}(self::f<self::A*>());
     super.{self::Base::member} = super.{self::Base::member}.{self::B::-}(1);
     super.{self::Base::member} = super.{self::Base::member}.{self::B::-}(1);
     self::B* v1 = super.{self::Base::member} = self::f<self::B*>();
     self::B* v2 = let final self::B* #t1 = super.{self::Base::member} in #t1.{core::Object::==}(null) ?{self::B*} super.{self::Base::member} = self::f<self::B*>() : #t1;
-    self::B* v4 = super.{self::Base::member} = super.{self::Base::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    self::C* v5 = super.{self::Base::member} = super.{self::Base::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    self::A* v3 = super.{self::Base::member} = super.{self::Base::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    self::B* v4 = super.{self::Base::member} = super.{self::Base::member}.{self::B::*}(self::f<self::B*>());
+    self::C* v5 = super.{self::Base::member} = super.{self::Base::member}.{self::B::&}(self::f<self::A*>());
     self::B* v6 = super.{self::Base::member} = super.{self::Base::member}.{self::B::-}(1);
     self::B* v7 = let final self::B* #t2 = super.{self::Base::member} in let final self::B* #t3 = super.{self::Base::member} = #t2.{self::B::-}(1) in #t2;
   }
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_super_upwards.dart b/pkg/front_end/testcases/inference/infer_assign_to_property_super_upwards.dart
index b906755..804769e 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_property_super_upwards.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_property_super_upwards.dart
@@ -17,33 +17,70 @@
 
 class Test1 extends Base {
   void test() {
-    var /*@ type=int* */ v1 = super. /*@target=Base::intProp*/ intProp = getInt();
+    var /*@ type=int* */ v1 =
+        super. /*@target=Base::intProp*/ intProp = getInt();
+
     var /*@ type=int* */ v4 =
-        super. /*@target=Base::intProp*/ intProp ??= getInt();
-    var /*@ type=int* */ v7 = super. /*@target=Base::intProp*/ intProp += getInt();
-    var /*@ type=int* */ v10 = ++super. /*@target=Base::intProp*/ intProp;
-    var /*@ type=int* */ v11 = super. /*@target=Base::intProp*/ intProp++;
+        super. /*@target=Base::intProp*/ /*@target=Base::intProp*/ intProp
+            /*@ target=num::==*/ ??= getInt();
+
+    var /*@ type=int* */ v7 =
+        super. /*@target=Base::intProp*/ /*@target=Base::intProp*/ intProp
+            /*@ target=num::+ */ += getInt();
+
+    var /*@ type=int* */ v10 = /*@ target=num::+ */ ++super
+        . /*@target=Base::intProp*/ /*@target=Base::intProp*/ intProp;
+
+    var /*@ type=int* */ v11 = super
+        . /*@ type=int* */ /*@target=Base::intProp*/ /*@target=Base::intProp*/
+        intProp /*@ type=int* */ /*@ target=num::+ */ ++;
   }
 }
 
 class Test2 extends Base {
   void test() {
-    var /*@ type=int* */ v1 = super. /*@target=Base::numProp*/ numProp = getInt();
-    var /*@ type=num* */ v2 = super. /*@target=Base::numProp*/ numProp = getNum();
+    var /*@ type=int* */ v1 =
+        super. /*@target=Base::numProp*/ numProp = getInt();
+
+    var /*@ type=num* */ v2 =
+        super. /*@target=Base::numProp*/ numProp = getNum();
+
     var /*@ type=double* */ v3 =
         super. /*@target=Base::numProp*/ numProp = getDouble();
+
     var /*@ type=num* */ v4 =
-        super. /*@target=Base::numProp*/ numProp ??= getInt();
+        super. /*@target=Base::numProp*/ /*@target=Base::numProp*/ numProp
+            /*@ target=num::==*/ ??= getInt();
+
     var /*@ type=num* */ v5 =
-        super. /*@target=Base::numProp*/ numProp ??= getNum();
+        super. /*@target=Base::numProp*/ /*@target=Base::numProp*/ numProp
+            /*@ target=num::==*/ ??= getNum();
+
     var /*@ type=num* */ v6 =
-        super. /*@target=Base::numProp*/ numProp ??= getDouble();
-    var /*@ type=num* */ v7 = super. /*@target=Base::numProp*/ numProp += getInt();
-    var /*@ type=num* */ v8 = super. /*@target=Base::numProp*/ numProp += getNum();
-    var /*@ type=num* */ v9 =
-        super. /*@target=Base::numProp*/ numProp += getDouble();
-    var /*@ type=num* */ v10 = ++super. /*@target=Base::numProp*/ numProp;
-    var /*@ type=num* */ v11 = super. /*@target=Base::numProp*/ numProp++;
+        super. /*@target=Base::numProp*/ /*@target=Base::numProp*/ numProp
+            /*@ target=num::==*/ ??= getDouble();
+
+    var /*@ type=num* */ v7 =
+        super. /*@target=Base::numProp*/ /*@target=Base::numProp*/ numProp
+            /*@ target=num::+ */ += getInt();
+
+    var /*@ type=num* */ v8 =
+        super. /*@target=Base::numProp*/ /*@target=Base::numProp*/ numProp
+            /*@ target=num::+ */ += getNum();
+
+    var /*@ type=num* */ v9 = super
+            .
+            /*@target=Base::numProp*/ /*@target=Base::numProp*/ numProp
+        /*@ target=num::+ */ += getDouble();
+
+    var /*@ type=num* */ v10 = /*@ target=num::+ */ ++super
+        . /*@target=Base::numProp*/ /*@target=Base::numProp*/ numProp;
+
+    var /*@ type=num* */ v11 = super
+            .
+            /*@ type=num* */ /*@target=Base::numProp*/ /*@target=Base::numProp*/
+            numProp
+        /*@ type=num* */ /*@ target=num::+ */ ++;
   }
 }
 
@@ -51,16 +88,30 @@
   void test3() {
     var /*@ type=double* */ v3 =
         super. /*@target=Base::doubleProp*/ doubleProp = getDouble();
-    var /*@ type=double* */ v6 =
-        super. /*@target=Base::doubleProp*/ doubleProp ??= getDouble();
-    var /*@ type=double* */ v7 =
-        super. /*@target=Base::doubleProp*/ doubleProp += getInt();
-    var /*@ type=double* */ v8 =
-        super. /*@target=Base::doubleProp*/ doubleProp += getNum();
-    var /*@ type=double* */ v9 =
-        super. /*@target=Base::doubleProp*/ doubleProp += getDouble();
-    var /*@ type=double* */ v10 = ++super. /*@target=Base::doubleProp*/ doubleProp;
-    var /*@ type=double* */ v11 = super. /*@target=Base::doubleProp*/ doubleProp++;
+
+    var /*@ type=double* */ v6 = super
+            . /*@target=Base::doubleProp*/ /*@target=Base::doubleProp*/ doubleProp
+        /*@ target=num::==*/ ??= getDouble();
+
+    var /*@ type=double* */ v7 = super
+            . /*@target=Base::doubleProp*/ /*@target=Base::doubleProp*/ doubleProp
+        /*@ target=double::+ */ += getInt();
+
+    var /*@ type=double* */ v8 = super
+            . /*@target=Base::doubleProp*/ /*@target=Base::doubleProp*/ doubleProp
+        /*@ target=double::+ */ += getNum();
+
+    var /*@ type=double* */ v9 = super
+            . /*@target=Base::doubleProp*/ /*@target=Base::doubleProp*/ doubleProp
+        /*@ target=double::+ */ += getDouble();
+
+    var /*@ type=double* */ v10 = /*@ target=double::+ */ ++super
+        . /*@target=Base::doubleProp*/ /*@target=Base::doubleProp*/ doubleProp;
+
+    var /*@ type=double* */ v11 = super
+            . /*@ type=double* */ /*@target=Base::doubleProp*/ /*@target=Base::doubleProp*/
+            doubleProp
+        /*@ type=double* */ /*@ target=double::+ */ ++;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_upwards.dart b/pkg/front_end/testcases/inference/infer_assign_to_property_upwards.dart
index 37e74b9..10dac09 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_property_upwards.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_property_upwards.dart
@@ -14,10 +14,18 @@
 
   static void test(Test1 t) {
     var /*@ type=int* */ v1 = t. /*@target=Test1::prop*/ prop = getInt();
-    var /*@ type=int* */ v4 = t. /*@target=Test1::prop*/ prop ??= getInt();
-    var /*@ type=int* */ v7 = t. /*@target=Test1::prop*/ prop += getInt();
-    var /*@ type=int* */ v10 = ++t. /*@target=Test1::prop*/ prop;
-    var /*@ type=int* */ v11 = t. /*@target=Test1::prop*/ prop++;
+    var /*@ type=int* */ v4 = /*@ type=Test1* */ t
+            . /*@target=Test1::prop*/ /*@target=Test1::prop*/ prop
+        /*@target=num::==*/ ??= getInt();
+    var /*@ type=int* */ v7 =
+        /*@ type=Test1* */ t
+                . /*@target=Test1::prop*/ /*@target=Test1::prop*/ prop
+            /*@ target=num::+ */ += getInt();
+    var /*@ type=int* */ v10 = /*@ target=num::+ */ ++ /*@ type=Test1* */ t
+        . /*@target=Test1::prop*/ /*@target=Test1::prop*/ prop;
+    var /*@ type=int* */ v11 = /*@ type=Test1* */ t
+        . /*@ type=int* */ /*@target=Test1::prop*/ /*@target=Test1::prop*/
+        prop /*@ type=int* */ /*@ target=num::+ */ ++;
   }
 }
 
@@ -28,14 +36,32 @@
     var /*@ type=int* */ v1 = t. /*@target=Test2::prop*/ prop = getInt();
     var /*@ type=num* */ v2 = t. /*@target=Test2::prop*/ prop = getNum();
     var /*@ type=double* */ v3 = t. /*@target=Test2::prop*/ prop = getDouble();
-    var /*@ type=num* */ v4 = t. /*@target=Test2::prop*/ prop ??= getInt();
-    var /*@ type=num* */ v5 = t. /*@target=Test2::prop*/ prop ??= getNum();
-    var /*@ type=num* */ v6 = t. /*@target=Test2::prop*/ prop ??= getDouble();
-    var /*@ type=num* */ v7 = t. /*@target=Test2::prop*/ prop += getInt();
-    var /*@ type=num* */ v8 = t. /*@target=Test2::prop*/ prop += getNum();
-    var /*@ type=num* */ v9 = t. /*@target=Test2::prop*/ prop += getDouble();
-    var /*@ type=num* */ v10 = ++t. /*@target=Test2::prop*/ prop;
-    var /*@ type=num* */ v11 = t. /*@target=Test2::prop*/ prop++;
+    var /*@ type=num* */ v4 = /*@ type=Test2* */ t
+            . /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+        /*@target=num::==*/ ??= getInt();
+    var /*@ type=num* */ v5 = /*@ type=Test2* */ t
+            . /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+        /*@target=num::==*/ ??= getNum();
+    var /*@ type=num* */ v6 = /*@ type=Test2* */ t
+            . /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+        /*@target=num::==*/ ??= getDouble();
+    var /*@ type=num* */ v7 =
+        /*@ type=Test2* */ t
+                . /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+            /*@ target=num::+ */ += getInt();
+    var /*@ type=num* */ v8 =
+        /*@ type=Test2* */ t
+                . /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+            /*@ target=num::+ */ += getNum();
+    var /*@ type=num* */ v9 =
+        /*@ type=Test2* */ t
+                . /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+            /*@ target=num::+ */ += getDouble();
+    var /*@ type=num* */ v10 = /*@ target=num::+ */ ++ /*@ type=Test2* */ t
+        . /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop;
+    var /*@ type=num* */ v11 = /*@ type=Test2* */ t
+        . /*@ type=num* */ /*@target=Test2::prop*/ /*@target=Test2::prop*/
+        prop /*@ type=num* */ /*@ target=num::+ */ ++;
   }
 }
 
@@ -44,12 +70,28 @@
 
   static void test3(Test3 t) {
     var /*@ type=double* */ v3 = t. /*@target=Test3::prop*/ prop = getDouble();
-    var /*@ type=double* */ v6 = t. /*@target=Test3::prop*/ prop ??= getDouble();
-    var /*@ type=double* */ v7 = t. /*@target=Test3::prop*/ prop += getInt();
-    var /*@ type=double* */ v8 = t. /*@target=Test3::prop*/ prop += getNum();
-    var /*@ type=double* */ v9 = t. /*@target=Test3::prop*/ prop += getDouble();
-    var /*@ type=double* */ v10 = ++t. /*@target=Test3::prop*/ prop;
-    var /*@ type=double* */ v11 = t. /*@target=Test3::prop*/ prop++;
+    var /*@ type=double* */ v6 =
+        /*@ type=Test3* */ t. /*@target=Test3::prop*/ /*@target=Test3::prop*/
+            prop /*@target=num::==*/ ??= getDouble();
+    var /*@ type=double* */ v7 =
+        /*@ type=Test3* */ t
+                . /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop
+            /*@ target=double::+ */ += getInt();
+    var /*@ type=double* */ v8 =
+        /*@ type=Test3* */ t
+                . /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop
+            /*@ target=double::+ */ += getNum();
+    var /*@ type=double* */ v9 =
+        /*@ type=Test3* */ t
+                . /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop
+            /*@ target=double::+ */ += getDouble();
+    var /*@ type=double* */ v10 = /*@ target=double::+ */ ++ /*@ type=Test3* */ t
+        .
+        /*@target=Test3::prop*/ /*@target=Test3::prop*/
+        prop;
+    var /*@ type=double* */ v11 = /*@ type=Test3* */ t.
+        /*@ type=double* */ /*@target=Test3::prop*/ /*@target=Test3::prop*/
+        prop /*@ type=double* */ /*@ target=double::+ */ ++;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_static.dart b/pkg/front_end/testcases/inference/infer_assign_to_static.dart
index 56a5f89..33bd5fe 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_static.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_static.dart
@@ -24,34 +24,72 @@
 
 void test_topLevelVariable() {
   topLevelVariable = /*@ typeArgs=B* */ f();
-  topLevelVariable ??= /*@ typeArgs=B* */ f();
-  topLevelVariable += /*@ typeArgs=dynamic */ f();
-  topLevelVariable *= /*@ typeArgs=dynamic */ f();
-  topLevelVariable &= /*@ typeArgs=dynamic */ f();
-  --topLevelVariable;
-  topLevelVariable--;
+
+  topLevelVariable /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
+  topLevelVariable /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+  topLevelVariable /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+  topLevelVariable /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+  /*@ target=B::- */ --topLevelVariable;
+
+  topLevelVariable /*@ target=B::- */ --;
+
   var /*@ type=B* */ v1 = topLevelVariable = /*@ typeArgs=B* */ f();
-  var /*@ type=B* */ v2 = topLevelVariable ??= /*@ typeArgs=B* */ f();
-  var /*@ type=B* */ v4 = topLevelVariable *= /*@ typeArgs=dynamic */ f();
-  var /*@ type=C* */ v5 = topLevelVariable &= /*@ typeArgs=dynamic */ f();
-  var /*@ type=B* */ v6 = --topLevelVariable;
-  var /*@ type=B* */ v7 = topLevelVariable--;
+
+  var /*@ type=B* */ v2 =
+      topLevelVariable /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
+  var /*@ type=A* */ v3 =
+      topLevelVariable /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+  var /*@ type=B* */ v4 =
+      topLevelVariable /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+  var /*@ type=C* */ v5 =
+      topLevelVariable /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+  var /*@ type=B* */ v6 = /*@ target=B::- */ --topLevelVariable;
+
+  var /*@ type=B* */ v7 = /*@ type=B* */ topLevelVariable
+      /*@ type=B* */ /*@ target=B::- */ --;
 }
 
 void test_staticVariable() {
   B.staticVariable = /*@ typeArgs=B* */ f();
-  B.staticVariable ??= /*@ typeArgs=B* */ f();
-  B.staticVariable += /*@ typeArgs=dynamic */ f();
-  B.staticVariable *= /*@ typeArgs=dynamic */ f();
-  B.staticVariable &= /*@ typeArgs=dynamic */ f();
-  --B.staticVariable;
-  B.staticVariable--;
+
+  B.staticVariable /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
+  B.staticVariable /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+  B.staticVariable /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+  B.staticVariable /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+  /*@ target=B::- */ --B.staticVariable;
+
+  B.staticVariable /*@ target=B::- */ --;
+
   var /*@ type=B* */ v1 = B.staticVariable = /*@ typeArgs=B* */ f();
-  var /*@ type=B* */ v2 = B.staticVariable ??= /*@ typeArgs=B* */ f();
-  var /*@ type=B* */ v4 = B.staticVariable *= /*@ typeArgs=dynamic */ f();
-  var /*@ type=C* */ v5 = B.staticVariable &= /*@ typeArgs=dynamic */ f();
-  var /*@ type=B* */ v6 = --B.staticVariable;
-  var /*@ type=B* */ v7 = B.staticVariable--;
+
+  var /*@ type=B* */ v2 =
+      B.staticVariable /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
+  var /*@ type=A* */ v3 =
+      B.staticVariable /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+  var /*@ type=B* */ v4 =
+      B.staticVariable /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+  var /*@ type=C* */ v5 =
+      B.staticVariable /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+  var /*@ type=B* */ v6 = /*@ target=B::- */ --B.staticVariable;
+
+  var /*@ type=B* */ v7 =
+      B. /*@ type=B* */ staticVariable /*@ type=B* */ /*@ target=B::- */ --;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_static.dart.strong.expect b/pkg/front_end/testcases/inference/infer_assign_to_static.dart.strong.expect
index 8ef6b74..2c07ffd 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_static.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_static.dart.strong.expect
@@ -32,30 +32,32 @@
 static method test_topLevelVariable() → void {
   self::topLevelVariable = self::f<self::B*>();
   self::topLevelVariable.{core::Object::==}(null) ?{self::B*} self::topLevelVariable = self::f<self::B*>() : null;
-  self::topLevelVariable = self::topLevelVariable.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-  self::topLevelVariable = self::topLevelVariable.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::topLevelVariable = self::topLevelVariable.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::topLevelVariable = self::topLevelVariable.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::topLevelVariable = self::topLevelVariable.{self::B::*}(self::f<self::B*>());
+  self::topLevelVariable = self::topLevelVariable.{self::B::&}(self::f<self::A*>());
   self::topLevelVariable = self::topLevelVariable.{self::B::-}(1);
   self::topLevelVariable = self::topLevelVariable.{self::B::-}(1);
   self::B* v1 = self::topLevelVariable = self::f<self::B*>();
   self::B* v2 = let final self::B* #t1 = self::topLevelVariable in #t1.{core::Object::==}(null) ?{self::B*} self::topLevelVariable = self::f<self::B*>() : #t1;
-  self::B* v4 = self::topLevelVariable = self::topLevelVariable.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::C* v5 = self::topLevelVariable = self::topLevelVariable.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::A* v3 = self::topLevelVariable = self::topLevelVariable.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::B* v4 = self::topLevelVariable = self::topLevelVariable.{self::B::*}(self::f<self::B*>());
+  self::C* v5 = self::topLevelVariable = self::topLevelVariable.{self::B::&}(self::f<self::A*>());
   self::B* v6 = self::topLevelVariable = self::topLevelVariable.{self::B::-}(1);
   self::B* v7 = let final self::B* #t2 = self::topLevelVariable in let final self::B* #t3 = self::topLevelVariable = #t2.{self::B::-}(1) in #t2;
 }
 static method test_staticVariable() → void {
   self::B::staticVariable = self::f<self::B*>();
   self::B::staticVariable.{core::Object::==}(null) ?{self::B*} self::B::staticVariable = self::f<self::B*>() : null;
-  self::B::staticVariable = self::B::staticVariable.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-  self::B::staticVariable = self::B::staticVariable.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::B::staticVariable = self::B::staticVariable.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::B::staticVariable = self::B::staticVariable.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::B::staticVariable = self::B::staticVariable.{self::B::*}(self::f<self::B*>());
+  self::B::staticVariable = self::B::staticVariable.{self::B::&}(self::f<self::A*>());
   self::B::staticVariable = self::B::staticVariable.{self::B::-}(1);
   self::B::staticVariable = self::B::staticVariable.{self::B::-}(1);
   self::B* v1 = self::B::staticVariable = self::f<self::B*>();
   self::B* v2 = let final self::B* #t4 = self::B::staticVariable in #t4.{core::Object::==}(null) ?{self::B*} self::B::staticVariable = self::f<self::B*>() : #t4;
-  self::B* v4 = self::B::staticVariable = self::B::staticVariable.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::C* v5 = self::B::staticVariable = self::B::staticVariable.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::A* v3 = self::B::staticVariable = self::B::staticVariable.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::B* v4 = self::B::staticVariable = self::B::staticVariable.{self::B::*}(self::f<self::B*>());
+  self::C* v5 = self::B::staticVariable = self::B::staticVariable.{self::B::&}(self::f<self::A*>());
   self::B* v6 = self::B::staticVariable = self::B::staticVariable.{self::B::-}(1);
   self::B* v7 = let final self::B* #t5 = self::B::staticVariable in let final self::B* #t6 = self::B::staticVariable = #t5.{self::B::-}(1) in #t5;
 }
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_static.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_assign_to_static.dart.strong.transformed.expect
index 8ef6b74..2c07ffd 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_static.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_assign_to_static.dart.strong.transformed.expect
@@ -32,30 +32,32 @@
 static method test_topLevelVariable() → void {
   self::topLevelVariable = self::f<self::B*>();
   self::topLevelVariable.{core::Object::==}(null) ?{self::B*} self::topLevelVariable = self::f<self::B*>() : null;
-  self::topLevelVariable = self::topLevelVariable.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-  self::topLevelVariable = self::topLevelVariable.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::topLevelVariable = self::topLevelVariable.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::topLevelVariable = self::topLevelVariable.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::topLevelVariable = self::topLevelVariable.{self::B::*}(self::f<self::B*>());
+  self::topLevelVariable = self::topLevelVariable.{self::B::&}(self::f<self::A*>());
   self::topLevelVariable = self::topLevelVariable.{self::B::-}(1);
   self::topLevelVariable = self::topLevelVariable.{self::B::-}(1);
   self::B* v1 = self::topLevelVariable = self::f<self::B*>();
   self::B* v2 = let final self::B* #t1 = self::topLevelVariable in #t1.{core::Object::==}(null) ?{self::B*} self::topLevelVariable = self::f<self::B*>() : #t1;
-  self::B* v4 = self::topLevelVariable = self::topLevelVariable.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::C* v5 = self::topLevelVariable = self::topLevelVariable.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::A* v3 = self::topLevelVariable = self::topLevelVariable.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::B* v4 = self::topLevelVariable = self::topLevelVariable.{self::B::*}(self::f<self::B*>());
+  self::C* v5 = self::topLevelVariable = self::topLevelVariable.{self::B::&}(self::f<self::A*>());
   self::B* v6 = self::topLevelVariable = self::topLevelVariable.{self::B::-}(1);
   self::B* v7 = let final self::B* #t2 = self::topLevelVariable in let final self::B* #t3 = self::topLevelVariable = #t2.{self::B::-}(1) in #t2;
 }
 static method test_staticVariable() → void {
   self::B::staticVariable = self::f<self::B*>();
   self::B::staticVariable.{core::Object::==}(null) ?{self::B*} self::B::staticVariable = self::f<self::B*>() : null;
-  self::B::staticVariable = self::B::staticVariable.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-  self::B::staticVariable = self::B::staticVariable.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::B::staticVariable = self::B::staticVariable.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::B::staticVariable = self::B::staticVariable.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::B::staticVariable = self::B::staticVariable.{self::B::*}(self::f<self::B*>());
+  self::B::staticVariable = self::B::staticVariable.{self::B::&}(self::f<self::A*>());
   self::B::staticVariable = self::B::staticVariable.{self::B::-}(1);
   self::B::staticVariable = self::B::staticVariable.{self::B::-}(1);
   self::B* v1 = self::B::staticVariable = self::f<self::B*>();
   self::B* v2 = let final self::B* #t4 = self::B::staticVariable in #t4.{core::Object::==}(null) ?{self::B*} self::B::staticVariable = self::f<self::B*>() : #t4;
-  self::B* v4 = self::B::staticVariable = self::B::staticVariable.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::C* v5 = self::B::staticVariable = self::B::staticVariable.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::A* v3 = self::B::staticVariable = self::B::staticVariable.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::B* v4 = self::B::staticVariable = self::B::staticVariable.{self::B::*}(self::f<self::B*>());
+  self::C* v5 = self::B::staticVariable = self::B::staticVariable.{self::B::&}(self::f<self::A*>());
   self::B* v6 = self::B::staticVariable = self::B::staticVariable.{self::B::-}(1);
   self::B* v7 = let final self::B* #t5 = self::B::staticVariable in let final self::B* #t6 = self::B::staticVariable = #t5.{self::B::-}(1) in #t5;
 }
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_static_upwards.dart b/pkg/front_end/testcases/inference/infer_assign_to_static_upwards.dart
index bfb7da2..eb199fc 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_static_upwards.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_static_upwards.dart
@@ -15,34 +15,61 @@
 
 void test1() {
   var /*@ type=int* */ v1 = topLevelInt = getInt();
-  var /*@ type=int* */ v4 = topLevelInt ??= getInt();
-  var /*@ type=int* */ v7 = topLevelInt += getInt();
-  var /*@ type=int* */ v10 = ++topLevelInt;
-  var /*@ type=int* */ v11 = topLevelInt++;
+
+  var /*@ type=int* */ v4 = topLevelInt /*@ target=num::== */ ??= getInt();
+
+  var /*@ type=int* */ v7 = topLevelInt /*@ target=num::+ */ += getInt();
+
+  var /*@ type=int* */ v10 = /*@ target=num::+ */ ++topLevelInt;
+
+  var /*@ type=int* */ v11 = /*@ type=int* */ topLevelInt
+      /*@ type=int* */ /*@ target=num::+ */ ++;
 }
 
 void test2() {
   var /*@ type=int* */ v1 = topLevelNum = getInt();
+
   var /*@ type=num* */ v2 = topLevelNum = getNum();
+
   var /*@ type=double* */ v3 = topLevelNum = getDouble();
-  var /*@ type=num* */ v4 = topLevelNum ??= getInt();
-  var /*@ type=num* */ v5 = topLevelNum ??= getNum();
-  var /*@ type=num* */ v6 = topLevelNum ??= getDouble();
-  var /*@ type=num* */ v7 = topLevelNum += getInt();
-  var /*@ type=num* */ v8 = topLevelNum += getNum();
-  var /*@ type=num* */ v9 = topLevelNum += getDouble();
-  var /*@ type=num* */ v10 = ++topLevelNum;
-  var /*@ type=num* */ v11 = topLevelNum++;
+
+  var /*@ type=num* */ v4 = topLevelNum /*@ target=num::== */ ??= getInt();
+
+  var /*@ type=num* */ v5 = topLevelNum /*@ target=num::== */ ??= getNum();
+
+  var /*@ type=num* */ v6 = topLevelNum /*@ target=num::== */ ??= getDouble();
+
+  var /*@ type=num* */ v7 = topLevelNum /*@ target=num::+ */ += getInt();
+
+  var /*@ type=num* */ v8 = topLevelNum /*@ target=num::+ */ += getNum();
+
+  var /*@ type=num* */ v9 = topLevelNum /*@ target=num::+ */ += getDouble();
+
+  var /*@ type=num* */ v10 = /*@ target=num::+ */ ++topLevelNum;
+
+  var /*@ type=num* */ v11 = /*@ type=num* */ topLevelNum
+      /*@ type=num* */ /*@ target=num::+ */ ++;
 }
 
 void test3() {
   var /*@ type=double* */ v3 = topLevelDouble = getDouble();
-  var /*@ type=double* */ v6 = topLevelDouble ??= getDouble();
-  var /*@ type=double* */ v7 = topLevelDouble += getInt();
-  var /*@ type=double* */ v8 = topLevelDouble += getNum();
-  var /*@ type=double* */ v9 = topLevelDouble += getDouble();
-  var /*@ type=double* */ v10 = ++topLevelDouble;
-  var /*@ type=double* */ v11 = topLevelDouble++;
+
+  var /*@ type=double* */ v6 =
+      topLevelDouble /*@ target=num::== */ ??= getDouble();
+
+  var /*@ type=double* */ v7 =
+      topLevelDouble /*@ target=double::+ */ += getInt();
+
+  var /*@ type=double* */ v8 =
+      topLevelDouble /*@ target=double::+ */ += getNum();
+
+  var /*@ type=double* */ v9 =
+      topLevelDouble /*@ target=double::+ */ += getDouble();
+
+  var /*@ type=double* */ v10 = /*@ target=double::+ */ ++topLevelDouble;
+
+  var /*@ type=double* */ v11 = /*@ type=double* */ topLevelDouble
+      /*@ type=double* */ /*@ target=double::+ */ ++;
 }
 
 main() {}
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 0122ef4..0dd5e96 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
@@ -134,33 +134,43 @@
                                    ^" in "hi" as{TypeError} self::B*;
   self::b = new self::B::•(3);
   self::c1 = <dynamic>[];
-  self::c1 = let final core::Set<dynamic>* #t5 = col::LinkedHashSet::•<dynamic>() in #t5;
+  self::c1 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:41:59: Error: A value of type 'Set<dynamic>' can't be assigned to a variable of type 'List<dynamic>'.
+ - 'Set' is from 'dart:core'.
+ - 'List' is from 'dart:core'.
+Try changing the type of the left hand side, or casting the right hand side to 'List<dynamic>'.
+  c1 = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic*/ {};
+                                                          ^" in (let final core::Set<dynamic>* #t6 = col::LinkedHashSet::•<dynamic>() in #t6) as{TypeError} core::List<dynamic>*;
   self::c2 = <dynamic>[];
-  self::c2 = let final core::Set<dynamic>* #t6 = col::LinkedHashSet::•<dynamic>() in #t6;
+  self::c2 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:43:59: Error: A value of type 'Set<dynamic>' can't be assigned to a variable of type 'List<dynamic>'.
+ - 'Set' is from 'dart:core'.
+ - 'List' is from 'dart:core'.
+Try changing the type of the left hand side, or casting the right hand side to 'List<dynamic>'.
+  c2 = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic*/ {};
+                                                          ^" in (let final core::Set<dynamic>* #t8 = col::LinkedHashSet::•<dynamic>() in #t8) as{TypeError} core::List<dynamic>*;
   self::d = <dynamic, dynamic>{};
-  self::d = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:45:36: Error: A value of type 'int' can't be assigned to a variable of type 'Map<dynamic, dynamic>'.
+  self::d = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:45:36: Error: A value of type 'int' can't be assigned to a variable of type 'Map<dynamic, dynamic>'.
  - 'Map' is from 'dart:core'.
 Try changing the type of the left hand side, or casting the right hand side to 'Map<dynamic, dynamic>'.
   d = /*error:INVALID_ASSIGNMENT*/ 3;
                                    ^" in 3 as{TypeError} core::Map<dynamic, dynamic>*;
   self::e = new self::A::•();
-  self::e = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:47:67: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'A'.
+  self::e = let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:47:67: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'A'.
  - 'Map' is from 'dart:core'.
  - 'A' is from 'pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart'.
 Try changing the type of the left hand side, or casting the right hand side to 'A'.
   e = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic, dynamic*/ {};
                                                                   ^" in <dynamic, dynamic>{} as{TypeError} self::A*;
   self::f = 3;
-  self::f = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:49:36: Error: A value of type 'bool' can't be assigned to a variable of type 'int'.
+  self::f = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:49:36: Error: A value of type 'bool' can't be assigned to a variable of type 'int'.
 Try changing the type of the left hand side, or casting the right hand side to 'int'.
   f = /*error:INVALID_ASSIGNMENT*/ false;
                                    ^" in false as{TypeError} core::int*;
   self::g = 1;
-  self::g = let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:51:36: Error: A value of type 'bool' can't be assigned to a variable of type 'int'.
+  self::g = let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:51:36: Error: A value of type 'bool' can't be assigned to a variable of type 'int'.
 Try changing the type of the left hand side, or casting the right hand side to 'int'.
   g = /*error:INVALID_ASSIGNMENT*/ false;
                                    ^" in false as{TypeError} core::int*;
-  self::h = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:52:36: Error: A value of type 'bool' can't be assigned to a variable of type 'B'.
+  self::h = let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:52:36: Error: A value of type 'bool' can't be assigned to a variable of type 'B'.
  - 'B' is from 'pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart'.
 Try changing the type of the left hand side, or casting the right hand side to 'B'.
   h = /*error:INVALID_ASSIGNMENT*/ false;
@@ -168,12 +178,12 @@
   self::h = new self::B::•("b");
   self::i = false;
   self::j = new self::B::•("b");
-  self::j = let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:56:36: Error: A value of type 'bool' can't be assigned to a variable of type 'B'.
+  self::j = let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:56:36: Error: A value of type 'bool' can't be assigned to a variable of type 'B'.
  - 'B' is from 'pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart'.
 Try changing the type of the left hand side, or casting the right hand side to 'B'.
   j = /*error:INVALID_ASSIGNMENT*/ false;
                                    ^" in false as{TypeError} self::B*;
-  self::j = let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:57:58: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'B'.
+  self::j = let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:57:58: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'B'.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart'.
 Try changing the type of the left hand side, or casting the right hand side to 'B'.
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 93049fd1..1766be7 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
@@ -1,107 +1,197 @@
 library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:19:46: Error: Getter not found: 'x'.
+// var b = new B(/*error:UNDEFINED_IDENTIFIER*/ x); // allocations
+//                                              ^
+//
+// pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:21:34: Error: Getter not found: 'x'.
+//   /*error:UNDEFINED_IDENTIFIER*/ x
+//                                  ^
+//
+// pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:32:58: Error: The method 'unary-' isn't defined for the class 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart'.
+// Try correcting the name to the name of an existing method, or defining a method named 'unary-'.
+// var i = /*error:UNDEFINED_OPERATOR,info:DYNAMIC_INVOKE*/ -new A();
+//                                                          ^
+//
+// pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:36:36: Error: A value of type 'String' can't be assigned to a variable of type 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart'.
+// Try changing the type of the left hand side, or casting the right hand side to 'A'.
+//   a = /*error:INVALID_ASSIGNMENT*/ "hi";
+//                                    ^
+//
+// pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:38:36: Error: A value of type 'String' can't be assigned to a variable of type 'B'.
+//  - 'B' is from 'pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart'.
+// Try changing the type of the left hand side, or casting the right hand side to 'B'.
+//   b = /*error:INVALID_ASSIGNMENT*/ "hi";
+//                                    ^
+//
+// pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:41:59: Error: A value of type 'Set<dynamic>' can't be assigned to a variable of type 'List<dynamic>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'List' is from 'dart:core'.
+// Try changing the type of the left hand side, or casting the right hand side to 'List<dynamic>'.
+//   c1 = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic*/ {};
+//                                                           ^
+//
+// pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:43:59: Error: A value of type 'Set<dynamic>' can't be assigned to a variable of type 'List<dynamic>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'List' is from 'dart:core'.
+// Try changing the type of the left hand side, or casting the right hand side to 'List<dynamic>'.
+//   c2 = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic*/ {};
+//                                                           ^
+//
+// pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:45:36: Error: A value of type 'int' can't be assigned to a variable of type 'Map<dynamic, dynamic>'.
+//  - 'Map' is from 'dart:core'.
+// Try changing the type of the left hand side, or casting the right hand side to 'Map<dynamic, dynamic>'.
+//   d = /*error:INVALID_ASSIGNMENT*/ 3;
+//                                    ^
+//
+// pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:47:67: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'A'.
+//  - 'Map' is from 'dart:core'.
+//  - 'A' is from 'pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart'.
+// Try changing the type of the left hand side, or casting the right hand side to 'A'.
+//   e = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic, dynamic*/ {};
+//                                                                   ^
+//
+// pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:49:36: Error: A value of type 'bool' can't be assigned to a variable of type 'int'.
+// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+//   f = /*error:INVALID_ASSIGNMENT*/ false;
+//                                    ^
+//
+// pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:51:36: Error: A value of type 'bool' can't be assigned to a variable of type 'int'.
+// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+//   g = /*error:INVALID_ASSIGNMENT*/ false;
+//                                    ^
+//
+// pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:52:36: Error: A value of type 'bool' can't be assigned to a variable of type 'B'.
+//  - 'B' is from 'pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart'.
+// Try changing the type of the left hand side, or casting the right hand side to 'B'.
+//   h = /*error:INVALID_ASSIGNMENT*/ false;
+//                                    ^
+//
+// pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:56:36: Error: A value of type 'bool' can't be assigned to a variable of type 'B'.
+//  - 'B' is from 'pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart'.
+// Try changing the type of the left hand side, or casting the right hand side to 'B'.
+//   j = /*error:INVALID_ASSIGNMENT*/ false;
+//                                    ^
+//
+// pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:57:58: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'B'.
+//  - 'List' is from 'dart:core'.
+//  - 'B' is from 'pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart'.
+// Try changing the type of the left hand side, or casting the right hand side to 'B'.
+//   j = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic*/ [];
+//                                                          ^
+//
 import self as self;
 import "dart:core" as core;
+import "dart:collection" as col;
 
 class A extends core::Object {
-  field core::int x = null;
-  synthetic constructor •() → self::A
+  field core::int* x = null;
+  synthetic constructor •() → self::A*
     : super core::Object::•()
     ;
-  operator +(dynamic other) → self::B
+  operator +(dynamic other) → self::B*
     return null;
 }
 class B extends self::A {
-  constructor •(dynamic ignore) → self::B
+  constructor •(dynamic ignore) → self::B*
     : super self::A::•()
     ;
 }
-static field self::A a = new self::A::•();
-static field self::B b = new self::B::•(invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:19:61: Error: Getter not found: 'x'.
-var  b = new B(/*error:UNDEFINED_IDENTIFIER*/ x); // allocations
-                                                            ^");
-static field core::List<dynamic> c1 = <dynamic>[invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:21:34: Error: Getter not found: 'x'.
+static field self::A* a = new self::A::•();
+static field self::B* b = new self::B::•(invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:19:46: Error: Getter not found: 'x'.
+var b = new B(/*error:UNDEFINED_IDENTIFIER*/ x); // allocations
+                                             ^");
+static field core::List<dynamic>* c1 = <dynamic>[invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:21:34: Error: Getter not found: 'x'.
   /*error:UNDEFINED_IDENTIFIER*/ x
                                  ^"];
-static field core::List<dynamic> c2 = const <dynamic>[];
-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 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);
-static field dynamic i = let final self::A #t3 = new self::A::•() in invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:34:79: Error: The method 'unary-' isn't defined for the class 'A'.
+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 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);
+static field dynamic i = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:32:58: Error: The method 'unary-' isn't defined for the class 'A'.
  - 'A' is from 'pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart'.
 Try correcting the name to the name of an existing method, or defining a method named 'unary-'.
-var  i = /*error:UNDEFINED_OPERATOR,info:DYNAMIC_INVOKE*/ -new A();
-                                                                              ^";
-static field self::B j = null as self::B;
+var i = /*error:UNDEFINED_OPERATOR,info:DYNAMIC_INVOKE*/ -new A();
+                                                         ^";
+static field self::B* j = null as self::B*;
 static method test1() → dynamic {
-  self::a = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:38:36: Error: A value of type 'String' can't be assigned to a variable of type 'A'.
+  self::a = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:36:36: Error: A value of type 'String' can't be assigned to a variable of type 'A'.
  - 'A' is from 'pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart'.
 Try changing the type of the left hand side, or casting the right hand side to 'A'.
   a = /*error:INVALID_ASSIGNMENT*/ \"hi\";
-                                   ^" in "hi" as{TypeError} self::A;
+                                   ^" in "hi" as{TypeError} self::A*;
   self::a = new self::B::•(3);
-  self::b = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:40:36: Error: A value of type 'String' can't be assigned to a variable of type 'B'.
+  self::b = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:38:36: Error: A value of type 'String' can't be assigned to a variable of type 'B'.
  - 'B' is from 'pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart'.
 Try changing the type of the left hand side, or casting the right hand side to 'B'.
   b = /*error:INVALID_ASSIGNMENT*/ \"hi\";
-                                   ^" in "hi" as{TypeError} self::B;
+                                   ^" in "hi" as{TypeError} self::B*;
   self::b = new self::B::•(3);
   self::c1 = <dynamic>[];
-  self::c1 = let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:43:68: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'List<dynamic>'.
- - 'Map' is from 'dart:core'.
+  self::c1 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:41:59: Error: A value of type 'Set<dynamic>' can't be assigned to a variable of type 'List<dynamic>'.
+ - 'Set' is from 'dart:core'.
  - 'List' is from 'dart:core'.
 Try changing the type of the left hand side, or casting the right hand side to 'List<dynamic>'.
-  c1 = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic, dynamic*/ {};
-                                                                   ^" in <dynamic, dynamic>{} as{TypeError} core::List<dynamic>;
+  c1 = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic*/ {};
+                                                          ^" in (let final core::Set<dynamic>* #t6 = col::LinkedHashSet::•<dynamic>() in #t6) as{TypeError} core::List<dynamic>*;
   self::c2 = <dynamic>[];
-  self::c2 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:45:68: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'List<dynamic>'.
- - 'Map' is from 'dart:core'.
+  self::c2 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:43:59: Error: A value of type 'Set<dynamic>' can't be assigned to a variable of type 'List<dynamic>'.
+ - 'Set' is from 'dart:core'.
  - 'List' is from 'dart:core'.
 Try changing the type of the left hand side, or casting the right hand side to 'List<dynamic>'.
-  c2 = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic, dynamic*/ {};
-                                                                   ^" in <dynamic, dynamic>{} as{TypeError} core::List<dynamic>;
+  c2 = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic*/ {};
+                                                          ^" in (let final core::Set<dynamic>* #t8 = col::LinkedHashSet::•<dynamic>() in #t8) as{TypeError} core::List<dynamic>*;
   self::d = <dynamic, dynamic>{};
-  self::d = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:47:36: Error: A value of type 'int' can't be assigned to a variable of type 'Map<dynamic, dynamic>'.
+  self::d = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:45:36: Error: A value of type 'int' can't be assigned to a variable of type 'Map<dynamic, dynamic>'.
  - 'Map' is from 'dart:core'.
 Try changing the type of the left hand side, or casting the right hand side to 'Map<dynamic, dynamic>'.
   d = /*error:INVALID_ASSIGNMENT*/ 3;
-                                   ^" in 3 as{TypeError} core::Map<dynamic, dynamic>;
+                                   ^" in 3 as{TypeError} core::Map<dynamic, dynamic>*;
   self::e = new self::A::•();
-  self::e = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:49:67: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'A'.
+  self::e = let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:47:67: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'A'.
  - 'Map' is from 'dart:core'.
  - 'A' is from 'pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart'.
 Try changing the type of the left hand side, or casting the right hand side to 'A'.
   e = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic, dynamic*/ {};
-                                                                  ^" in <dynamic, dynamic>{} as{TypeError} self::A;
+                                                                  ^" in <dynamic, dynamic>{} as{TypeError} self::A*;
   self::f = 3;
-  self::f = let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:51:36: Error: A value of type 'bool' can't be assigned to a variable of type 'int'.
+  self::f = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:49:36: Error: A value of type 'bool' can't be assigned to a variable of type 'int'.
 Try changing the type of the left hand side, or casting the right hand side to 'int'.
   f = /*error:INVALID_ASSIGNMENT*/ false;
-                                   ^" in false as{TypeError} core::int;
+                                   ^" in false as{TypeError} core::int*;
   self::g = 1;
-  self::g = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:53:36: Error: A value of type 'bool' can't be assigned to a variable of type 'int'.
+  self::g = let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:51:36: Error: A value of type 'bool' can't be assigned to a variable of type 'int'.
 Try changing the type of the left hand side, or casting the right hand side to 'int'.
   g = /*error:INVALID_ASSIGNMENT*/ false;
-                                   ^" in false as{TypeError} core::int;
-  self::h = let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:54:36: Error: A value of type 'bool' can't be assigned to a variable of type 'B'.
+                                   ^" in false as{TypeError} core::int*;
+  self::h = let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:52:36: Error: A value of type 'bool' can't be assigned to a variable of type 'B'.
  - 'B' is from 'pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart'.
 Try changing the type of the left hand side, or casting the right hand side to 'B'.
   h = /*error:INVALID_ASSIGNMENT*/ false;
-                                   ^" in false as{TypeError} self::B;
+                                   ^" in false as{TypeError} self::B*;
   self::h = new self::B::•("b");
   self::i = false;
   self::j = new self::B::•("b");
-  self::j = let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:58:36: Error: A value of type 'bool' can't be assigned to a variable of type 'B'.
+  self::j = let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:56:36: Error: A value of type 'bool' can't be assigned to a variable of type 'B'.
  - 'B' is from 'pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart'.
 Try changing the type of the left hand side, or casting the right hand side to 'B'.
   j = /*error:INVALID_ASSIGNMENT*/ false;
-                                   ^" in false as{TypeError} self::B;
-  self::j = let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:59:58: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'B'.
+                                   ^" in false as{TypeError} self::B*;
+  self::j = let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:57:58: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'B'.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart'.
 Try changing the type of the left hand side, or casting the right hand side to 'B'.
   j = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic*/ [];
-                                                         ^" in <dynamic>[] as{TypeError} self::B;
+                                                         ^" in <dynamic>[] as{TypeError} self::B*;
 }
 static method main() → dynamic {}
+
+constants  {
+  #C1 = <dynamic>[]
+}
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart
index 963a6a0..46e0672 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart
+++ b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart
@@ -6,7 +6,9 @@
 library test;
 
 test() {
-  for (var /*@ type=int* */ i = 0; i /*@target=num::<*/ < 10; i++) {
+  for (var /*@ type=int* */ i = 0;
+      i /*@target=num::<*/ < 10;
+      i /*@ target=num::+ */ ++) {
     int j = i /*@target=num::+*/ + 1;
   }
 }
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart.type_promotion.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart.type_promotion.expect
index 5e037d0..dabdbac 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart.type_promotion.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart.type_promotion.expect
@@ -1,3 +1,3 @@
-pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart:9:64: Context: Write to i@299
-  for (var /*@ type=int* */ i = 0; i /*@target=num::<*/ < 10; i++) {
-                                                               ^^
+pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_loop_with_inference.dart:11:30: Context: Write to i@299
+      i /*@ target=num::+ */ ++) {
+                             ^^
diff --git a/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart b/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart
index dab289a..f1fd89e 100644
--- a/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart
+++ b/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart
@@ -6,5 +6,5 @@
 library test;
 
 main() {
-  var /*@ type=() ->* Null* */ f = /*@ returnType=Null* */ () {};
+  var /*@ type=() ->* Null? */ f = /*@ returnType=Null? */ () {};
 }
diff --git a/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart.strong.expect b/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart.strong.expect
index 12479df..64040c7 100644
--- a/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart.strong.expect
@@ -3,5 +3,5 @@
 import "dart:core" as core;
 
 static method main() → dynamic {
-  () →* core::Null* f = () → core::Null* {};
+  () →* core::Null? f = () → core::Null? {};
 }
diff --git a/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart.strong.transformed.expect
index 12479df..64040c7 100644
--- a/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return.dart.strong.transformed.expect
@@ -3,5 +3,5 @@
 import "dart:core" as core;
 
 static method main() → dynamic {
-  () →* core::Null* f = () → core::Null* {};
+  () →* core::Null? f = () → core::Null? {};
 }
diff --git a/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart b/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart
index 713085c..0d24e42 100644
--- a/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart
+++ b/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart
@@ -10,5 +10,5 @@
 }
 
 main() {
-  var /*@ type=C* */ c = new C(/*@ returnType=Null* */ () {});
+  var /*@ type=C* */ c = new C(/*@ returnType=Null? */ () {});
 }
diff --git a/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart.strong.expect b/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart.strong.expect
index b33a922..e20719a 100644
--- a/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart.strong.expect
@@ -7,5 +7,5 @@
     : super core::Object::•() {}
 }
 static method main() → dynamic {
-  self::C* c = new self::C::•(() → core::Null* {});
+  self::C* c = new self::C::•(() → core::Null? {});
 }
diff --git a/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart.strong.transformed.expect
index b33a922..e20719a 100644
--- a/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_block_closure_no_args_no_return_void_context.dart.strong.transformed.expect
@@ -7,5 +7,5 @@
     : super core::Object::•() {}
 }
 static method main() → dynamic {
-  self::C* c = new self::C::•(() → core::Null* {});
+  self::C* c = new self::C::•(() → core::Null? {});
 }
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart b/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart
index afc7289..58437b6 100644
--- a/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart
+++ b/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart
@@ -6,7 +6,7 @@
 library test;
 
 class C<T> {
-  void Function(T) f<U>(U x) => /*@ returnType=Null* */ (/*@ type=C::T* */ y) {};
+  void Function(T) f<U>(U x) => /*@ returnType=Null? */ (/*@ type=C::T* */ y) {};
 }
 
 void test(C<String> c) {
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.expect b/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.expect
index d7f5411..4d47083 100644
--- a/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
   method f<U extends core::Object* = dynamic>(self::C::f::U* x) → (self::C::T*) →* void
-    return (self::C::T* y) → core::Null* {};
+    return (self::C::T* y) → core::Null? {};
 }
 static method test(self::C<core::String*>* c) → void {
   (core::int*) →* (core::String*) →* void tearoff = c.{self::C::f} as{TypeError} <U extends core::Object* = dynamic>(U*) →* (core::String*) →* void<core::int*>;
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.transformed.expect
index d7f5411..4d47083 100644
--- a/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.transformed.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
   method f<U extends core::Object* = dynamic>(self::C::f::U* x) → (self::C::T*) →* void
-    return (self::C::T* y) → core::Null* {};
+    return (self::C::T* y) → core::Null? {};
 }
 static method test(self::C<core::String*>* c) → void {
   (core::int*) →* (core::String*) →* void tearoff = c.{self::C::f} as{TypeError} <U extends core::Object* = dynamic>(U*) →* (core::String*) →* void<core::int*>;
diff --git a/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart b/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart
index 3ed4a7e..52be7b9 100644
--- a/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart
+++ b/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart
@@ -6,7 +6,7 @@
 library test;
 
 test1() {
-  var /*@ type=List<Null*>* */ x = /*@ typeArgs=Null* */ [null];
+  var /*@ type=List<Null?>* */ x = /*@ typeArgs=Null? */ [null];
   x. /*@target=List::add*/ add(/*error:INVALID_CAST_LITERAL*/ 42);
 }
 
diff --git a/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.strong.expect b/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.strong.expect
index 11889f3..dafc04b 100644
--- a/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 static method test1() → dynamic {
-  core::List<core::Null*>* x = <core::Null*>[null];
-  x.{core::List::add}(42 as{TypeError} core::Null*);
+  core::List<core::Null?>* x = <core::Null?>[null];
+  x.{core::List::add}(42 as{TypeError} core::Null?);
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.strong.transformed.expect
index 11889f3..dafc04b 100644
--- a/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 static method test1() → dynamic {
-  core::List<core::Null*>* x = <core::Null*>[null];
-  x.{core::List::add}(42 as{TypeError} core::Null*);
+  core::List<core::Null?>* x = <core::Null?>[null];
+  x.{core::List::add}(42 as{TypeError} core::Null?);
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/map_literals.dart.strong.expect b/pkg/front_end/testcases/inference/map_literals.dart.strong.expect
index 3436fff..2449679 100644
--- a/pkg/front_end/testcases/inference/map_literals.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/map_literals.dart.strong.expect
@@ -2,29 +2,29 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/map_literals.dart:12:46: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
-// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+// pkg/front_end/testcases/inference/map_literals.dart:12:46: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// Try changing the type of the parameter, or casting the argument to 'int'.
 //       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
 //                                              ^
 //
-// pkg/front_end/testcases/inference/map_literals.dart:14:46: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
-// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+// pkg/front_end/testcases/inference/map_literals.dart:14:46: Error: The argument type 'double' can't be assigned to the parameter type 'int'.
+// Try changing the type of the parameter, or casting the argument to 'int'.
 //       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 4.0] = 'u';
 //                                              ^
 //
-// pkg/front_end/testcases/inference/map_literals.dart:15:61: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
-// Try changing the type of the left hand side, or casting the right hand side to 'String'.
+// pkg/front_end/testcases/inference/map_literals.dart:15:61: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
+// Try changing the type of the parameter, or casting the argument to 'String'.
 //   x /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
 //                                                             ^
 //
-// pkg/front_end/testcases/inference/map_literals.dart:27:46: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
-// Try changing the type of the left hand side, or casting the right hand side to 'num'.
+// pkg/front_end/testcases/inference/map_literals.dart:27:46: Error: The argument type 'String' can't be assigned to the parameter type 'num'.
+// Try changing the type of the parameter, or casting the argument to 'num'.
 //       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
 //                                              ^
 //
-// pkg/front_end/testcases/inference/map_literals.dart:29:61: Error: A value of type 'int' can't be assigned to a variable of type 'Pattern'.
+// pkg/front_end/testcases/inference/map_literals.dart:29:61: Error: The argument type 'int' can't be assigned to the parameter type 'Pattern'.
 //  - 'Pattern' is from 'dart:core'.
-// Try changing the type of the left hand side, or casting the right hand side to 'Pattern'.
+// Try changing the type of the parameter, or casting the argument to 'Pattern'.
 //   x /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
 //                                                             ^
 //
@@ -34,16 +34,16 @@
 static method test1() → dynamic {
   core::Map<core::int*, core::String*>* x = <core::int*, core::String*>{1: "x", 2: "y"};
   x.{core::Map::[]=}(3, "z");
-  x.{core::Map::[]=}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:12:46: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
-Try changing the type of the left hand side, or casting the right hand side to 'int'.
+  x.{core::Map::[]=}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:12:46: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+Try changing the type of the parameter, or casting the argument to 'int'.
       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
                                              ^" in "hi" as{TypeError} core::int*, "w");
-  x.{core::Map::[]=}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:14:46: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
-Try changing the type of the left hand side, or casting the right hand side to 'int'.
+  x.{core::Map::[]=}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:14:46: Error: The argument type 'double' can't be assigned to the parameter type 'int'.
+Try changing the type of the parameter, or casting the argument to 'int'.
       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 4.0] = 'u';
                                              ^" in 4.0 as{TypeError} core::int*, "u");
-  x.{core::Map::[]=}(3, let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:15:61: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
-Try changing the type of the left hand side, or casting the right hand side to 'String'.
+  x.{core::Map::[]=}(3, let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:15:61: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
+Try changing the type of the parameter, or casting the argument to 'String'.
   x /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
                                                             ^" in 42 as{TypeError} core::String*);
   core::Map<core::num*, core::String*>* y = x;
@@ -51,14 +51,14 @@
 static method test2() → dynamic {
   core::Map<core::num*, core::Pattern*>* x = <core::num*, core::Pattern*>{1: "x", 2: "y", 3.0: core::RegExp::•(".")};
   x.{core::Map::[]=}(3, "z");
-  x.{core::Map::[]=}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:27:46: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
-Try changing the type of the left hand side, or casting the right hand side to 'num'.
+  x.{core::Map::[]=}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:27:46: Error: The argument type 'String' can't be assigned to the parameter type 'num'.
+Try changing the type of the parameter, or casting the argument to 'num'.
       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
                                              ^" in "hi" as{TypeError} core::num*, "w");
   x.{core::Map::[]=}(4.0, "u");
-  x.{core::Map::[]=}(3, let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:29:61: Error: A value of type 'int' can't be assigned to a variable of type 'Pattern'.
+  x.{core::Map::[]=}(3, let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:29:61: Error: The argument type 'int' can't be assigned to the parameter type 'Pattern'.
  - 'Pattern' is from 'dart:core'.
-Try changing the type of the left hand side, or casting the right hand side to 'Pattern'.
+Try changing the type of the parameter, or casting the argument to 'Pattern'.
   x /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
                                                             ^" in 42 as{TypeError} core::Pattern*);
   core::Pattern* p = null;
diff --git a/pkg/front_end/testcases/inference/map_literals.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/map_literals.dart.strong.transformed.expect
index 3436fff..2449679 100644
--- a/pkg/front_end/testcases/inference/map_literals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/map_literals.dart.strong.transformed.expect
@@ -2,29 +2,29 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/map_literals.dart:12:46: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
-// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+// pkg/front_end/testcases/inference/map_literals.dart:12:46: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// Try changing the type of the parameter, or casting the argument to 'int'.
 //       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
 //                                              ^
 //
-// pkg/front_end/testcases/inference/map_literals.dart:14:46: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
-// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+// pkg/front_end/testcases/inference/map_literals.dart:14:46: Error: The argument type 'double' can't be assigned to the parameter type 'int'.
+// Try changing the type of the parameter, or casting the argument to 'int'.
 //       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 4.0] = 'u';
 //                                              ^
 //
-// pkg/front_end/testcases/inference/map_literals.dart:15:61: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
-// Try changing the type of the left hand side, or casting the right hand side to 'String'.
+// pkg/front_end/testcases/inference/map_literals.dart:15:61: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
+// Try changing the type of the parameter, or casting the argument to 'String'.
 //   x /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
 //                                                             ^
 //
-// pkg/front_end/testcases/inference/map_literals.dart:27:46: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
-// Try changing the type of the left hand side, or casting the right hand side to 'num'.
+// pkg/front_end/testcases/inference/map_literals.dart:27:46: Error: The argument type 'String' can't be assigned to the parameter type 'num'.
+// Try changing the type of the parameter, or casting the argument to 'num'.
 //       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
 //                                              ^
 //
-// pkg/front_end/testcases/inference/map_literals.dart:29:61: Error: A value of type 'int' can't be assigned to a variable of type 'Pattern'.
+// pkg/front_end/testcases/inference/map_literals.dart:29:61: Error: The argument type 'int' can't be assigned to the parameter type 'Pattern'.
 //  - 'Pattern' is from 'dart:core'.
-// Try changing the type of the left hand side, or casting the right hand side to 'Pattern'.
+// Try changing the type of the parameter, or casting the argument to 'Pattern'.
 //   x /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
 //                                                             ^
 //
@@ -34,16 +34,16 @@
 static method test1() → dynamic {
   core::Map<core::int*, core::String*>* x = <core::int*, core::String*>{1: "x", 2: "y"};
   x.{core::Map::[]=}(3, "z");
-  x.{core::Map::[]=}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:12:46: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
-Try changing the type of the left hand side, or casting the right hand side to 'int'.
+  x.{core::Map::[]=}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:12:46: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+Try changing the type of the parameter, or casting the argument to 'int'.
       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
                                              ^" in "hi" as{TypeError} core::int*, "w");
-  x.{core::Map::[]=}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:14:46: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
-Try changing the type of the left hand side, or casting the right hand side to 'int'.
+  x.{core::Map::[]=}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:14:46: Error: The argument type 'double' can't be assigned to the parameter type 'int'.
+Try changing the type of the parameter, or casting the argument to 'int'.
       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 4.0] = 'u';
                                              ^" in 4.0 as{TypeError} core::int*, "u");
-  x.{core::Map::[]=}(3, let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:15:61: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
-Try changing the type of the left hand side, or casting the right hand side to 'String'.
+  x.{core::Map::[]=}(3, let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:15:61: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
+Try changing the type of the parameter, or casting the argument to 'String'.
   x /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
                                                             ^" in 42 as{TypeError} core::String*);
   core::Map<core::num*, core::String*>* y = x;
@@ -51,14 +51,14 @@
 static method test2() → dynamic {
   core::Map<core::num*, core::Pattern*>* x = <core::num*, core::Pattern*>{1: "x", 2: "y", 3.0: core::RegExp::•(".")};
   x.{core::Map::[]=}(3, "z");
-  x.{core::Map::[]=}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:27:46: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
-Try changing the type of the left hand side, or casting the right hand side to 'num'.
+  x.{core::Map::[]=}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:27:46: Error: The argument type 'String' can't be assigned to the parameter type 'num'.
+Try changing the type of the parameter, or casting the argument to 'num'.
       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
                                              ^" in "hi" as{TypeError} core::num*, "w");
   x.{core::Map::[]=}(4.0, "u");
-  x.{core::Map::[]=}(3, let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:29:61: Error: A value of type 'int' can't be assigned to a variable of type 'Pattern'.
+  x.{core::Map::[]=}(3, let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/map_literals.dart:29:61: Error: The argument type 'int' can't be assigned to the parameter type 'Pattern'.
  - 'Pattern' is from 'dart:core'.
-Try changing the type of the left hand side, or casting the right hand side to 'Pattern'.
+Try changing the type of the parameter, or casting the argument to 'Pattern'.
   x /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
                                                             ^" in 42 as{TypeError} core::Pattern*);
   core::Pattern* p = null;
diff --git a/pkg/front_end/testcases/inference/map_literals_can_infer_null.dart b/pkg/front_end/testcases/inference/map_literals_can_infer_null.dart
index 1d3ab85..5cce7ec 100644
--- a/pkg/front_end/testcases/inference/map_literals_can_infer_null.dart
+++ b/pkg/front_end/testcases/inference/map_literals_can_infer_null.dart
@@ -6,7 +6,7 @@
 library test;
 
 test1() {
-  var /*@ type=Map<Null*, Null*>* */ x = /*@ typeArgs=Null*, Null* */ {null: null};
+  var /*@ type=Map<Null?, Null?>* */ x = /*@ typeArgs=Null?, Null? */ {null: null};
   x /*@target=Map::[]=*/ [
       /*error:INVALID_CAST_LITERAL*/ 3] = /*error:INVALID_CAST_LITERAL*/ 'z';
 }
diff --git a/pkg/front_end/testcases/inference/map_literals_can_infer_null.dart.strong.expect b/pkg/front_end/testcases/inference/map_literals_can_infer_null.dart.strong.expect
index 57e9d39..38d6f76 100644
--- a/pkg/front_end/testcases/inference/map_literals_can_infer_null.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/map_literals_can_infer_null.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 static method test1() → dynamic {
-  core::Map<core::Null*, core::Null*>* x = <core::Null*, core::Null*>{null: null};
-  x.{core::Map::[]=}(3 as{TypeError} core::Null*, "z" as{TypeError} core::Null*);
+  core::Map<core::Null?, core::Null?>* x = <core::Null?, core::Null?>{null: null};
+  x.{core::Map::[]=}(3 as{TypeError} core::Null?, "z" as{TypeError} core::Null?);
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/map_literals_can_infer_null.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/map_literals_can_infer_null.dart.strong.transformed.expect
index 57e9d39..38d6f76 100644
--- a/pkg/front_end/testcases/inference/map_literals_can_infer_null.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/map_literals_can_infer_null.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 static method test1() → dynamic {
-  core::Map<core::Null*, core::Null*>* x = <core::Null*, core::Null*>{null: null};
-  x.{core::Map::[]=}(3 as{TypeError} core::Null*, "z" as{TypeError} core::Null*);
+  core::Map<core::Null?, core::Null?>* x = <core::Null?, core::Null?>{null: null};
+  x.{core::Map::[]=}(3 as{TypeError} core::Null?, "z" as{TypeError} core::Null?);
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/map_literals_top_level.dart.strong.expect b/pkg/front_end/testcases/inference/map_literals_top_level.dart.strong.expect
index 0fb8116..7af3179 100644
--- a/pkg/front_end/testcases/inference/map_literals_top_level.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/map_literals_top_level.dart.strong.expect
@@ -2,29 +2,29 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:11:67: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
-// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:11:67: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// Try changing the type of the parameter, or casting the argument to 'int'.
 //   x1 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
 //                                                                   ^
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:12:67: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
-// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:12:67: Error: The argument type 'double' can't be assigned to the parameter type 'int'.
+// Try changing the type of the parameter, or casting the argument to 'int'.
 //   x1 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 4.0] = 'u';
 //                                                                   ^
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:13:62: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
-// Try changing the type of the left hand side, or casting the right hand side to 'String'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:13:62: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
+// Try changing the type of the parameter, or casting the argument to 'String'.
 //   x1 /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
 //                                                              ^
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:20:67: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
-// Try changing the type of the left hand side, or casting the right hand side to 'num'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:20:67: Error: The argument type 'String' can't be assigned to the parameter type 'num'.
+// Try changing the type of the parameter, or casting the argument to 'num'.
 //   x2 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
 //                                                                   ^
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:22:62: Error: A value of type 'int' can't be assigned to a variable of type 'Pattern'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:22:62: Error: The argument type 'int' can't be assigned to the parameter type 'Pattern'.
 //  - 'Pattern' is from 'dart:core'.
-// Try changing the type of the left hand side, or casting the right hand side to 'Pattern'.
+// Try changing the type of the parameter, or casting the argument to 'Pattern'.
 //   x2 /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
 //                                                              ^
 //
@@ -35,30 +35,30 @@
 static field core::Map<core::num*, core::Pattern*>* x2 = <core::num*, core::Pattern*>{1: "x", 2: "y", 3.0: core::RegExp::•(".")};
 static method test1() → dynamic {
   self::x1.{core::Map::[]=}(3, "z");
-  self::x1.{core::Map::[]=}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:11:67: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
-Try changing the type of the left hand side, or casting the right hand side to 'int'.
+  self::x1.{core::Map::[]=}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:11:67: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+Try changing the type of the parameter, or casting the argument to 'int'.
   x1 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
                                                                   ^" in "hi" as{TypeError} core::int*, "w");
-  self::x1.{core::Map::[]=}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:12:67: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
-Try changing the type of the left hand side, or casting the right hand side to 'int'.
+  self::x1.{core::Map::[]=}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:12:67: Error: The argument type 'double' can't be assigned to the parameter type 'int'.
+Try changing the type of the parameter, or casting the argument to 'int'.
   x1 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 4.0] = 'u';
                                                                   ^" in 4.0 as{TypeError} core::int*, "u");
-  self::x1.{core::Map::[]=}(3, let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:13:62: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
-Try changing the type of the left hand side, or casting the right hand side to 'String'.
+  self::x1.{core::Map::[]=}(3, let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:13:62: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
+Try changing the type of the parameter, or casting the argument to 'String'.
   x1 /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
                                                              ^" in 42 as{TypeError} core::String*);
   core::Map<core::num*, core::String*>* y = self::x1;
 }
 static method test2() → dynamic {
   self::x2.{core::Map::[]=}(3, "z");
-  self::x2.{core::Map::[]=}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:20:67: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
-Try changing the type of the left hand side, or casting the right hand side to 'num'.
+  self::x2.{core::Map::[]=}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:20:67: Error: The argument type 'String' can't be assigned to the parameter type 'num'.
+Try changing the type of the parameter, or casting the argument to 'num'.
   x2 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
                                                                   ^" in "hi" as{TypeError} core::num*, "w");
   self::x2.{core::Map::[]=}(4.0, "u");
-  self::x2.{core::Map::[]=}(3, let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:22:62: Error: A value of type 'int' can't be assigned to a variable of type 'Pattern'.
+  self::x2.{core::Map::[]=}(3, let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:22:62: Error: The argument type 'int' can't be assigned to the parameter type 'Pattern'.
  - 'Pattern' is from 'dart:core'.
-Try changing the type of the left hand side, or casting the right hand side to 'Pattern'.
+Try changing the type of the parameter, or casting the argument to 'Pattern'.
   x2 /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
                                                              ^" in 42 as{TypeError} core::Pattern*);
   core::Pattern* p = null;
diff --git a/pkg/front_end/testcases/inference/map_literals_top_level.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/map_literals_top_level.dart.strong.transformed.expect
index 0fb8116..7af3179 100644
--- a/pkg/front_end/testcases/inference/map_literals_top_level.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/map_literals_top_level.dart.strong.transformed.expect
@@ -2,29 +2,29 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:11:67: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
-// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:11:67: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// Try changing the type of the parameter, or casting the argument to 'int'.
 //   x1 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
 //                                                                   ^
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:12:67: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
-// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:12:67: Error: The argument type 'double' can't be assigned to the parameter type 'int'.
+// Try changing the type of the parameter, or casting the argument to 'int'.
 //   x1 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 4.0] = 'u';
 //                                                                   ^
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:13:62: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
-// Try changing the type of the left hand side, or casting the right hand side to 'String'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:13:62: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
+// Try changing the type of the parameter, or casting the argument to 'String'.
 //   x1 /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
 //                                                              ^
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:20:67: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
-// Try changing the type of the left hand side, or casting the right hand side to 'num'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:20:67: Error: The argument type 'String' can't be assigned to the parameter type 'num'.
+// Try changing the type of the parameter, or casting the argument to 'num'.
 //   x2 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
 //                                                                   ^
 //
-// pkg/front_end/testcases/inference/map_literals_top_level.dart:22:62: Error: A value of type 'int' can't be assigned to a variable of type 'Pattern'.
+// pkg/front_end/testcases/inference/map_literals_top_level.dart:22:62: Error: The argument type 'int' can't be assigned to the parameter type 'Pattern'.
 //  - 'Pattern' is from 'dart:core'.
-// Try changing the type of the left hand side, or casting the right hand side to 'Pattern'.
+// Try changing the type of the parameter, or casting the argument to 'Pattern'.
 //   x2 /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
 //                                                              ^
 //
@@ -35,30 +35,30 @@
 static field core::Map<core::num*, core::Pattern*>* x2 = <core::num*, core::Pattern*>{1: "x", 2: "y", 3.0: core::RegExp::•(".")};
 static method test1() → dynamic {
   self::x1.{core::Map::[]=}(3, "z");
-  self::x1.{core::Map::[]=}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:11:67: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
-Try changing the type of the left hand side, or casting the right hand side to 'int'.
+  self::x1.{core::Map::[]=}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:11:67: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+Try changing the type of the parameter, or casting the argument to 'int'.
   x1 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
                                                                   ^" in "hi" as{TypeError} core::int*, "w");
-  self::x1.{core::Map::[]=}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:12:67: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
-Try changing the type of the left hand side, or casting the right hand side to 'int'.
+  self::x1.{core::Map::[]=}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:12:67: Error: The argument type 'double' can't be assigned to the parameter type 'int'.
+Try changing the type of the parameter, or casting the argument to 'int'.
   x1 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 4.0] = 'u';
                                                                   ^" in 4.0 as{TypeError} core::int*, "u");
-  self::x1.{core::Map::[]=}(3, let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:13:62: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
-Try changing the type of the left hand side, or casting the right hand side to 'String'.
+  self::x1.{core::Map::[]=}(3, let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:13:62: Error: The argument type 'int' can't be assigned to the parameter type 'String'.
+Try changing the type of the parameter, or casting the argument to 'String'.
   x1 /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
                                                              ^" in 42 as{TypeError} core::String*);
   core::Map<core::num*, core::String*>* y = self::x1;
 }
 static method test2() → dynamic {
   self::x2.{core::Map::[]=}(3, "z");
-  self::x2.{core::Map::[]=}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:20:67: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
-Try changing the type of the left hand side, or casting the right hand side to 'num'.
+  self::x2.{core::Map::[]=}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:20:67: Error: The argument type 'String' can't be assigned to the parameter type 'num'.
+Try changing the type of the parameter, or casting the argument to 'num'.
   x2 /*@target=Map::[]=*/ [/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi'] = 'w';
                                                                   ^" in "hi" as{TypeError} core::num*, "w");
   self::x2.{core::Map::[]=}(4.0, "u");
-  self::x2.{core::Map::[]=}(3, let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:22:62: Error: A value of type 'int' can't be assigned to a variable of type 'Pattern'.
+  self::x2.{core::Map::[]=}(3, let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/map_literals_top_level.dart:22:62: Error: The argument type 'int' can't be assigned to the parameter type 'Pattern'.
  - 'Pattern' is from 'dart:core'.
-Try changing the type of the left hand side, or casting the right hand side to 'Pattern'.
+Try changing the type of the parameter, or casting the argument to 'Pattern'.
   x2 /*@target=Map::[]=*/ [3] = /*error:INVALID_ASSIGNMENT*/ 42;
                                                              ^" in 42 as{TypeError} core::Pattern*);
   core::Pattern* p = null;
diff --git a/pkg/front_end/testcases/inference/null_aware_method_invocation.dart b/pkg/front_end/testcases/inference/null_aware_method_invocation.dart
index 13e2704..62e84f5 100644
--- a/pkg/front_end/testcases/inference/null_aware_method_invocation.dart
+++ b/pkg/front_end/testcases/inference/null_aware_method_invocation.dart
@@ -10,8 +10,9 @@
 }
 
 g(C c) {
-  var /*@ type=int* */ x = c?. /*@target=C::f*/ f();
-  c?. /*@target=C::f*/ f();
+  var /*@ type=int* */ x = /*@ type=C* */ /*@target=Object::==*/ c
+      ?. /*@target=C::f*/ f();
+  /*@ type=C* */ /*@target=Object::==*/ c?. /*@target=C::f*/ f();
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/null_aware_method_invocation.dart.strong.expect b/pkg/front_end/testcases/inference/null_aware_method_invocation.dart.strong.expect
index 718b355..127fa61 100644
--- a/pkg/front_end/testcases/inference/null_aware_method_invocation.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/null_aware_method_invocation.dart.strong.expect
@@ -10,7 +10,7 @@
     return null;
 }
 static method g(self::C* c) → dynamic {
-  core::int* x = let final self::C* #t1 = c in #t1.==(null) ?{core::int*} null : #t1.{self::C::f}();
-  let final self::C* #t2 = c in #t2.==(null) ?{core::int*} null : #t2.{self::C::f}();
+  core::int* x = let final self::C* #t1 = c in #t1.{core::Object::==}(null) ?{core::int*} null : #t1.{self::C::f}();
+  let final self::C* #t2 = c in #t2.{core::Object::==}(null) ?{core::int*} null : #t2.{self::C::f}();
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/null_aware_method_invocation.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/null_aware_method_invocation.dart.strong.transformed.expect
index 718b355..127fa61 100644
--- a/pkg/front_end/testcases/inference/null_aware_method_invocation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/null_aware_method_invocation.dart.strong.transformed.expect
@@ -10,7 +10,7 @@
     return null;
 }
 static method g(self::C* c) → dynamic {
-  core::int* x = let final self::C* #t1 = c in #t1.==(null) ?{core::int*} null : #t1.{self::C::f}();
-  let final self::C* #t2 = c in #t2.==(null) ?{core::int*} null : #t2.{self::C::f}();
+  core::int* x = let final self::C* #t1 = c in #t1.{core::Object::==}(null) ?{core::int*} null : #t1.{self::C::f}();
+  let final self::C* #t2 = c in #t2.{core::Object::==}(null) ?{core::int*} null : #t2.{self::C::f}();
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/null_aware_property_get.dart b/pkg/front_end/testcases/inference/null_aware_property_get.dart
index f565a26..112432b 100644
--- a/pkg/front_end/testcases/inference/null_aware_property_get.dart
+++ b/pkg/front_end/testcases/inference/null_aware_property_get.dart
@@ -10,8 +10,9 @@
 }
 
 void f(C c) {
-  var /*@ type=int* */ x = c?. /*@target=C::x*/ x;
-  c?. /*@target=C::x*/ x;
+  var /*@ type=int* */ x = /*@ type=C* */ /*@target=Object::==*/ c
+      ?. /*@target=C::x*/ x;
+  /*@ type=C* */ /*@target=Object::==*/ c?. /*@target=C::x*/ x;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/null_aware_property_get.dart.strong.expect b/pkg/front_end/testcases/inference/null_aware_property_get.dart.strong.expect
index 4c40eb5..0d14e2b 100644
--- a/pkg/front_end/testcases/inference/null_aware_property_get.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/null_aware_property_get.dart.strong.expect
@@ -9,7 +9,7 @@
     ;
 }
 static method f(self::C* c) → void {
-  core::int* x = let final self::C* #t1 = c in #t1.==(null) ?{core::int*} null : #t1.{self::C::x};
-  let final self::C* #t2 = c in #t2.==(null) ?{core::int*} null : #t2.{self::C::x};
+  core::int* x = let final self::C* #t1 = c in #t1.{core::Object::==}(null) ?{core::int*} null : #t1.{self::C::x};
+  let final self::C* #t2 = c in #t2.{core::Object::==}(null) ?{core::int*} null : #t2.{self::C::x};
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/null_aware_property_get.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/null_aware_property_get.dart.strong.transformed.expect
index 4c40eb5..0d14e2b 100644
--- a/pkg/front_end/testcases/inference/null_aware_property_get.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/null_aware_property_get.dart.strong.transformed.expect
@@ -9,7 +9,7 @@
     ;
 }
 static method f(self::C* c) → void {
-  core::int* x = let final self::C* #t1 = c in #t1.==(null) ?{core::int*} null : #t1.{self::C::x};
-  let final self::C* #t2 = c in #t2.==(null) ?{core::int*} null : #t2.{self::C::x};
+  core::int* x = let final self::C* #t1 = c in #t1.{core::Object::==}(null) ?{core::int*} null : #t1.{self::C::x};
+  let final self::C* #t2 = c in #t2.{core::Object::==}(null) ?{core::int*} null : #t2.{self::C::x};
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart b/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart
index 2bcd9b9..42550db 100644
--- a/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart
+++ b/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart
@@ -9,10 +9,10 @@
 void foo(int f(Object _)) {}
 
 test() {
-  var /*@ type=(Object*) ->* Null* */ f = /*@ returnType=Null* */ (Object x) => null;
+  var /*@ type=(Object*) ->* Null? */ f = /*@ returnType=Null? */ (Object x) => null;
   String y = /*info:DYNAMIC_CAST*/ f(42);
 
-  f = /*@ returnType=Null* */ (/*@ type=Object* */ x) => 'hello';
+  f = /*@ returnType=Null? */ (/*@ type=Object* */ x) => 'hello';
 
   var /*@ type=dynamic */ g = null;
   g = 'hello';
@@ -21,7 +21,7 @@
   h = 'hello';
   (/*info:DYNAMIC_INVOKE*/ h.foo());
 
-  foo(/*@ returnType=Null* */ (/*@ type=Object* */ x) => null);
+  foo(/*@ returnType=Null? */ (/*@ type=Object* */ x) => null);
   foo(/*@ returnType=<BottomType> */ (/*@ type=Object* */ x) =>
       throw "not implemented");
 }
diff --git a/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.strong.expect b/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.strong.expect
index f63bf12..20b5208 100644
--- a/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.strong.expect
@@ -5,15 +5,15 @@
 static field dynamic h = null;
 static method foo((core::Object*) →* core::int* f) → void {}
 static method test() → dynamic {
-  (core::Object*) →* core::Null* f = (core::Object* x) → core::Null* => null;
+  (core::Object*) →* core::Null? f = (core::Object* x) → core::Null? => null;
   core::String* y = f.call(42);
-  f = (core::Object* x) → core::Null* => "hello" as{TypeError} core::Null*;
+  f = (core::Object* x) → core::Null? => "hello" as{TypeError} core::Null?;
   dynamic g = null;
   g = "hello";
   g.foo();
   self::h = "hello";
   self::h.foo();
-  self::foo((core::Object* x) → core::Null* => null);
+  self::foo((core::Object* x) → core::Null? => null);
   self::foo((core::Object* x) → <BottomType>=> throw "not implemented");
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.strong.transformed.expect
index f63bf12..20b5208 100644
--- a/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.strong.transformed.expect
@@ -5,15 +5,15 @@
 static field dynamic h = null;
 static method foo((core::Object*) →* core::int* f) → void {}
 static method test() → dynamic {
-  (core::Object*) →* core::Null* f = (core::Object* x) → core::Null* => null;
+  (core::Object*) →* core::Null? f = (core::Object* x) → core::Null? => null;
   core::String* y = f.call(42);
-  f = (core::Object* x) → core::Null* => "hello" as{TypeError} core::Null*;
+  f = (core::Object* x) → core::Null? => "hello" as{TypeError} core::Null?;
   dynamic g = null;
   g = "hello";
   g.foo();
   self::h = "hello";
   self::h.foo();
-  self::foo((core::Object* x) → core::Null* => null);
+  self::foo((core::Object* x) → core::Null? => null);
   self::foo((core::Object* x) → <BottomType>=> throw "not implemented");
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.type_promotion.expect b/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.type_promotion.expect
index 43e9255..9262c18 100644
--- a/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.type_promotion.expect
+++ b/pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart.type_promotion.expect
@@ -1,5 +1,5 @@
 pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart:15:5: Context: Write to f@353
-  f = /*@ returnType=Null* */ (/*@ type=Object* */ x) => 'hello';
+  f = /*@ returnType=Null? */ (/*@ type=Object* */ x) => 'hello';
     ^
 pkg/front_end/testcases/inference/null_literal_should_not_infer_as_bottom.dart:18:5: Context: Write to g@537
   g = 'hello';
diff --git a/pkg/front_end/testcases/inference/parameter_defaults_downwards.dart b/pkg/front_end/testcases/inference/parameter_defaults_downwards.dart
index 668875a..b0671b2 100644
--- a/pkg/front_end/testcases/inference/parameter_defaults_downwards.dart
+++ b/pkg/front_end/testcases/inference/parameter_defaults_downwards.dart
@@ -12,8 +12,8 @@
 main() {
   void optional_local([List<int> x = /*@ typeArgs=int* */ const []]) {}
   void named_local({List<int> x: /*@ typeArgs=int* */ const []}) {}
-  var /*@ type=([List<int*>*]) ->* Null* */ optional_closure = /*@ returnType=Null* */ (
+  var /*@ type=([List<int*>*]) ->* Null? */ optional_closure = /*@ returnType=Null? */ (
       [List<int> x = /*@ typeArgs=int* */ const []]) {};
-  var /*@ type=({x: List<int*>*}) ->* Null* */ name_closure = /*@ returnType=Null* */ (
+  var /*@ type=({x: List<int*>*}) ->* Null? */ name_closure = /*@ returnType=Null? */ (
       {List<int> x: /*@ typeArgs=int* */ const []}) {};
 }
diff --git a/pkg/front_end/testcases/inference/parameter_defaults_downwards.dart.strong.expect b/pkg/front_end/testcases/inference/parameter_defaults_downwards.dart.strong.expect
index 27d3688..0c97dce 100644
--- a/pkg/front_end/testcases/inference/parameter_defaults_downwards.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/parameter_defaults_downwards.dart.strong.expect
@@ -7,8 +7,8 @@
 static method main() → dynamic {
   function optional_local([core::List<core::int*>* x = #C1]) → void {}
   function named_local({core::List<core::int*>* x = #C1}) → void {}
-  ([core::List<core::int*>*]) →* core::Null* optional_closure = ([core::List<core::int*>* x = #C1]) → core::Null* {};
-  ({x: core::List<core::int*>*}) →* core::Null* name_closure = ({core::List<core::int*>* x = #C1}) → core::Null* {};
+  ([core::List<core::int*>*]) →* core::Null? optional_closure = ([core::List<core::int*>* x = #C1]) → core::Null? {};
+  ({x: core::List<core::int*>*}) →* core::Null? name_closure = ({core::List<core::int*>* x = #C1}) → core::Null? {};
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/inference/parameter_defaults_downwards.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/parameter_defaults_downwards.dart.strong.transformed.expect
index 27d3688..0c97dce 100644
--- a/pkg/front_end/testcases/inference/parameter_defaults_downwards.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/parameter_defaults_downwards.dart.strong.transformed.expect
@@ -7,8 +7,8 @@
 static method main() → dynamic {
   function optional_local([core::List<core::int*>* x = #C1]) → void {}
   function named_local({core::List<core::int*>* x = #C1}) → void {}
-  ([core::List<core::int*>*]) →* core::Null* optional_closure = ([core::List<core::int*>* x = #C1]) → core::Null* {};
-  ({x: core::List<core::int*>*}) →* core::Null* name_closure = ({core::List<core::int*>* x = #C1}) → core::Null* {};
+  ([core::List<core::int*>*]) →* core::Null? optional_closure = ([core::List<core::int*>* x = #C1]) → core::Null? {};
+  ({x: core::List<core::int*>*}) →* core::Null? name_closure = ({core::List<core::int*>* x = #C1}) → core::Null? {};
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart b/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart
index 067eba9..ce97e95 100644
--- a/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart
+++ b/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart
@@ -26,9 +26,9 @@
   var /*@ type=C<dynamic>* */ c_named_local =
       new /*@ typeArgs=dynamic */ C.named(named_local);
   var /*@ type=C<dynamic>* */ c_optional_closure =
-      new /*@ typeArgs=dynamic */ C.optional(/*@ returnType=Null* */ (
+      new /*@ typeArgs=dynamic */ C.optional(/*@ returnType=Null? */ (
           [/*@ type=dynamic */ x = /*@ typeArgs=int* */ const [0]]) {});
   var /*@ type=C<dynamic>* */ c_named_closure = new /*@ typeArgs=dynamic */ C.named(
-      /*@ returnType=Null* */ (
+      /*@ returnType=Null? */ (
           {/*@ type=dynamic */ x: /*@ typeArgs=int* */ const [0]}) {});
 }
diff --git a/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.strong.expect b/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.strong.expect
index 163f232..f26bb4a 100644
--- a/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.strong.expect
@@ -17,8 +17,8 @@
   self::C<dynamic>* c_named_toplevel = new self::C::named<dynamic>(#C4);
   self::C<dynamic>* c_optional_local = new self::C::optional<dynamic>(optional_local);
   self::C<dynamic>* c_named_local = new self::C::named<dynamic>(named_local);
-  self::C<dynamic>* c_optional_closure = new self::C::optional<dynamic>(([dynamic x = #C2]) → core::Null* {});
-  self::C<dynamic>* c_named_closure = new self::C::named<dynamic>(({dynamic x = #C2}) → core::Null* {});
+  self::C<dynamic>* c_optional_closure = new self::C::optional<dynamic>(([dynamic x = #C2]) → core::Null? {});
+  self::C<dynamic>* c_named_closure = new self::C::named<dynamic>(({dynamic x = #C2}) → core::Null? {});
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.strong.transformed.expect
index 163f232..f26bb4a 100644
--- a/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.strong.transformed.expect
@@ -17,8 +17,8 @@
   self::C<dynamic>* c_named_toplevel = new self::C::named<dynamic>(#C4);
   self::C<dynamic>* c_optional_local = new self::C::optional<dynamic>(optional_local);
   self::C<dynamic>* c_named_local = new self::C::named<dynamic>(named_local);
-  self::C<dynamic>* c_optional_closure = new self::C::optional<dynamic>(([dynamic x = #C2]) → core::Null* {});
-  self::C<dynamic>* c_named_closure = new self::C::named<dynamic>(({dynamic x = #C2}) → core::Null* {});
+  self::C<dynamic>* c_optional_closure = new self::C::optional<dynamic>(([dynamic x = #C2]) → core::Null? {});
+  self::C<dynamic>* c_named_closure = new self::C::named<dynamic>(({dynamic x = #C2}) → core::Null? {});
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart b/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart
index f8fdf0b..747ad06 100644
--- a/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart
+++ b/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart
@@ -9,7 +9,7 @@
   num n = null;
   if (n is int) {
     var /*@ type=num* */ i = n;
-    /*@ returnType=Null* */ () {
+    /*@ returnType=Null? */ () {
       n;
     };
   }
diff --git a/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.strong.expect b/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.strong.expect
index ae61a78..830f06e 100644
--- a/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.strong.expect
@@ -6,7 +6,7 @@
   core::num* n = null;
   if(n is core::int*) {
     core::num* i = n;
-    () → core::Null* {
+    () → core::Null? {
       n;
     };
   }
diff --git a/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.strong.transformed.expect
index ae61a78..830f06e 100644
--- a/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/type_promotion_stopped_by_access_in_a_closure.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
   core::num* n = null;
   if(n is core::int*) {
     core::num* i = n;
-    () → core::Null* {
+    () → core::Null? {
       n;
     };
   }
diff --git a/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart b/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart
index 17ce8b7..dbbc0b1 100644
--- a/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart
+++ b/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart
@@ -10,7 +10,7 @@
   if (n is int) {
     var /*@ type=num* */ i = n;
   }
-  /*@ returnType=Null* */ () {
+  /*@ returnType=Null? */ () {
     n = null;
   };
 }
diff --git a/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.strong.expect b/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.strong.expect
index 9cf4976..41ec7b8 100644
--- a/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.strong.expect
@@ -7,7 +7,7 @@
   if(n is core::int*) {
     core::num* i = n;
   }
-  () → core::Null* {
+  () → core::Null? {
     n = null;
   };
 }
diff --git a/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.strong.transformed.expect
index 9cf4976..41ec7b8 100644
--- a/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/type_promotion_stopped_by_mutation_in_a_closure.dart.strong.transformed.expect
@@ -7,7 +7,7 @@
   if(n is core::int*) {
     core::num* i = n;
   }
-  () → core::Null* {
+  () → core::Null? {
     n = null;
   };
 }
diff --git a/pkg/front_end/testcases/inference_new/const_invocation.dart b/pkg/front_end/testcases/inference_new/const_invocation.dart
index c707af5..8525174 100644
--- a/pkg/front_end/testcases/inference_new/const_invocation.dart
+++ b/pkg/front_end/testcases/inference_new/const_invocation.dart
@@ -8,16 +8,16 @@
 typedef V F<U, V>(U u);
 
 class Foo<T> {
-  Bar<T> get v1 => const /*@ typeArgs=Null* */ Bar();
-  Bar<List<T>> get v2 => const /*@ typeArgs=List<Null*>* */ Bar();
-  Bar<F<T, T>> get v3 => const /*@ typeArgs=(Object*) ->* Null* */ Bar();
+  Bar<T> get v1 => const /*@ typeArgs=Null? */ Bar();
+  Bar<List<T>> get v2 => const /*@ typeArgs=List<Null?>* */ Bar();
+  Bar<F<T, T>> get v3 => const /*@ typeArgs=(Object*) ->* Null? */ Bar();
   Bar<F<F<T, T>, T>> get v4 =>
-      const /*@ typeArgs=((Null*) ->* Object*) ->* Null* */ Bar();
-  List<T> get v5 => /*@ typeArgs=Null* */ const [];
-  List<F<T, T>> get v6 => /*@ typeArgs=(Object*) ->* Null* */ const [];
-  Map<T, T> get v7 => /*@ typeArgs=Null*, Null* */ const {};
-  Map<F<T, T>, T> get v8 => /*@ typeArgs=(Object*) ->* Null*, Null* */ const {};
-  Map<T, F<T, T>> get v9 => /*@ typeArgs=Null*, (Object*) ->* Null* */ const {};
+      const /*@ typeArgs=((Null?) ->* Object*) ->* Null? */ Bar();
+  List<T> get v5 => /*@ typeArgs=Null? */ const [];
+  List<F<T, T>> get v6 => /*@ typeArgs=(Object*) ->* Null? */ const [];
+  Map<T, T> get v7 => /*@ typeArgs=Null?, Null? */ const {};
+  Map<F<T, T>, T> get v8 => /*@ typeArgs=(Object*) ->* Null?, Null? */ const {};
+  Map<T, F<T, T>> get v9 => /*@ typeArgs=Null?, (Object*) ->* Null? */ const {};
 }
 
 class Bar<T> {
diff --git a/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.expect b/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.expect
index 6d0c538..c1f792b 100644
--- a/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.expect
@@ -34,14 +34,14 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = self::Bar<core::Null*> {}
-  #C2 = self::Bar<core::List<core::Null*>*> {}
-  #C3 = self::Bar<(core::Object*) →* core::Null*> {}
-  #C4 = self::Bar<((core::Null*) →* core::Object*) →* core::Null*> {}
-  #C5 = <core::Null*>[]
-  #C6 = <(core::Object*) →* core::Null*>[]
+  #C1 = self::Bar<core::Null?> {}
+  #C2 = self::Bar<core::List<core::Null?>*> {}
+  #C3 = self::Bar<(core::Object*) →* core::Null?> {}
+  #C4 = self::Bar<((core::Null?) →* core::Object*) →* core::Null?> {}
+  #C5 = <core::Null?>[]
+  #C6 = <(core::Object*) →* core::Null?>[]
   #C7 = <dynamic>[]
-  #C8 = core::_ImmutableMap<core::Null*, core::Null*> {_kvPairs:#C7}
-  #C9 = core::_ImmutableMap<(core::Object*) →* core::Null*, core::Null*> {_kvPairs:#C7}
-  #C10 = core::_ImmutableMap<core::Null*, (core::Object*) →* core::Null*> {_kvPairs:#C7}
+  #C8 = core::_ImmutableMap<core::Null?, core::Null?> {_kvPairs:#C7}
+  #C9 = core::_ImmutableMap<(core::Object*) →* core::Null?, core::Null?> {_kvPairs:#C7}
+  #C10 = core::_ImmutableMap<core::Null?, (core::Object*) →* core::Null?> {_kvPairs:#C7}
 }
diff --git a/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.transformed.expect
index 6d0c538..c1f792b 100644
--- a/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.transformed.expect
@@ -34,14 +34,14 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = self::Bar<core::Null*> {}
-  #C2 = self::Bar<core::List<core::Null*>*> {}
-  #C3 = self::Bar<(core::Object*) →* core::Null*> {}
-  #C4 = self::Bar<((core::Null*) →* core::Object*) →* core::Null*> {}
-  #C5 = <core::Null*>[]
-  #C6 = <(core::Object*) →* core::Null*>[]
+  #C1 = self::Bar<core::Null?> {}
+  #C2 = self::Bar<core::List<core::Null?>*> {}
+  #C3 = self::Bar<(core::Object*) →* core::Null?> {}
+  #C4 = self::Bar<((core::Null?) →* core::Object*) →* core::Null?> {}
+  #C5 = <core::Null?>[]
+  #C6 = <(core::Object*) →* core::Null?>[]
   #C7 = <dynamic>[]
-  #C8 = core::_ImmutableMap<core::Null*, core::Null*> {_kvPairs:#C7}
-  #C9 = core::_ImmutableMap<(core::Object*) →* core::Null*, core::Null*> {_kvPairs:#C7}
-  #C10 = core::_ImmutableMap<core::Null*, (core::Object*) →* core::Null*> {_kvPairs:#C7}
+  #C8 = core::_ImmutableMap<core::Null?, core::Null?> {_kvPairs:#C7}
+  #C9 = core::_ImmutableMap<(core::Object*) →* core::Null?, core::Null?> {_kvPairs:#C7}
+  #C10 = core::_ImmutableMap<core::Null?, (core::Object*) →* core::Null?> {_kvPairs:#C7}
 }
diff --git a/pkg/front_end/testcases/inference_new/for_each_identifier_downwards.dart b/pkg/front_end/testcases/inference_new/for_each_identifier_downwards.dart
index 1f79cf3..968995d 100644
--- a/pkg/front_end/testcases/inference_new/for_each_identifier_downwards.dart
+++ b/pkg/front_end/testcases/inference_new/for_each_identifier_downwards.dart
@@ -18,9 +18,15 @@
   void test() {
     A aLocal;
     for (aLocal in /*@ typeArgs=Iterable<A*>* */ f()) {}
-    for (/*@target=C::aField*/ aField in /*@ typeArgs=Iterable<A*>* */ f()) {}
-    for (/*@target=C::aSetter*/ aSetter in /*@ typeArgs=Iterable<A*>* */ f()) {}
+
+    for (/*@target=C::aField*/ /*@target=C::aField*/ aField
+        in /*@ typeArgs=Iterable<A*>* */ f()) {}
+
+    for (/*@target=C::aSetter*/ /*@target=C::aSetter*/ aSetter
+        in /*@ typeArgs=Iterable<A*>* */ f()) {}
+
     for (aTopLevel in /*@ typeArgs=Iterable<A*>* */ f()) {}
+
     for (aTopLevelSetter in /*@ typeArgs=Iterable<A*>* */ f()) {}
   }
 }
diff --git a/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart b/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart
index f3ca5eb..6b8a751 100644
--- a/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart
+++ b/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart
@@ -32,18 +32,23 @@
 }
 
 void test1(G g) {
-  g /*@target=G::[]=*/ [0] *= /*@ typeArgs=dynamic */ f();
-  var /*@ type=C* */ x = g /*@target=G::[]=*/ [0] *= /*@ typeArgs=dynamic */ f();
+  g /*@target=G::[]*/ /*@target=G::[]=*/ [
+      0] /*@ target=A::* */ *= /*@ typeArgs=D* */ f();
+  var /*@ type=C* */ x = g /*@target=G::[]*/ /*@target=G::[]=*/ [0]
+      /*@ target=A::* */
+      *= /*@ typeArgs=D* */ f();
 }
 
 void test2(G g) {
-  ++g /*@target=G::[]=*/ [0];
-  var /*@ type=C* */ x = ++g /*@target=G::[]=*/ [0];
+  /*@ target=A::+ */ ++g /*@target=G::[]*/ /*@target=G::[]=*/ [0];
+  var /*@ type=C* */ x = /*@ target=A::+ */ ++g /*@target=G::[]*/ /*@target=G::[]=*/ [
+      0];
 }
 
 void test3(G g) {
-  g /*@target=G::[]=*/ [0]++;
-  var /*@ type=A* */ x = g /*@target=G::[]=*/ [0]++;
+  g /*@target=G::[] */ /*@target=G::[]=*/ [0] /*@ target=A::+ */ ++;
+  var /*@ type=A* */ x =
+      g /*@target=G::[]*/ /*@target=G::[]=*/ [0] /*@ target=A::+ */ ++;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.strong.expect b/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.strong.expect
index be01111..0d07bfd 100644
--- a/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.strong.expect
@@ -51,8 +51,8 @@
 static method f<T extends core::Object* = dynamic>() → self::f::T*
   return null;
 static method test1(self::G* g) → void {
-  let final self::G* #t1 = g in let final core::int* #t2 = 0 in #t1.{self::G::[]=}(#t2, #t1.{self::G::[]}(#t2).{self::A::*}(self::f<dynamic>() as{TypeError} self::D*));
-  self::C* x = let final self::G* #t3 = g in let final core::int* #t4 = 0 in let final self::C* #t5 = #t3.{self::G::[]}(#t4).{self::A::*}(self::f<dynamic>() as{TypeError} self::D*) in let final void #t6 = #t3.{self::G::[]=}(#t4, #t5) in #t5;
+  let final self::G* #t1 = g in let final core::int* #t2 = 0 in #t1.{self::G::[]=}(#t2, #t1.{self::G::[]}(#t2).{self::A::*}(self::f<self::D*>()));
+  self::C* x = let final self::G* #t3 = g in let final core::int* #t4 = 0 in let final self::C* #t5 = #t3.{self::G::[]}(#t4).{self::A::*}(self::f<self::D*>()) in let final void #t6 = #t3.{self::G::[]=}(#t4, #t5) in #t5;
 }
 static method test2(self::G* g) → void {
   let final self::G* #t7 = g in let final core::int* #t8 = 0 in let final self::C* #t9 = #t7.{self::G::[]}(#t8).{self::A::+}(1) in let final void #t10 = #t7.{self::G::[]=}(#t8, #t9) in #t9;
diff --git a/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.strong.transformed.expect
index be01111..0d07bfd 100644
--- a/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.strong.transformed.expect
@@ -51,8 +51,8 @@
 static method f<T extends core::Object* = dynamic>() → self::f::T*
   return null;
 static method test1(self::G* g) → void {
-  let final self::G* #t1 = g in let final core::int* #t2 = 0 in #t1.{self::G::[]=}(#t2, #t1.{self::G::[]}(#t2).{self::A::*}(self::f<dynamic>() as{TypeError} self::D*));
-  self::C* x = let final self::G* #t3 = g in let final core::int* #t4 = 0 in let final self::C* #t5 = #t3.{self::G::[]}(#t4).{self::A::*}(self::f<dynamic>() as{TypeError} self::D*) in let final void #t6 = #t3.{self::G::[]=}(#t4, #t5) in #t5;
+  let final self::G* #t1 = g in let final core::int* #t2 = 0 in #t1.{self::G::[]=}(#t2, #t1.{self::G::[]}(#t2).{self::A::*}(self::f<self::D*>()));
+  self::C* x = let final self::G* #t3 = g in let final core::int* #t4 = 0 in let final self::C* #t5 = #t3.{self::G::[]}(#t4).{self::A::*}(self::f<self::D*>()) in let final void #t6 = #t3.{self::G::[]=}(#t4, #t5) in #t5;
 }
 static method test2(self::G* g) → void {
   let final self::G* #t7 = g in let final core::int* #t8 = 0 in let final self::C* #t9 = #t7.{self::G::[]}(#t8).{self::A::+}(1) in let final void #t10 = #t7.{self::G::[]=}(#t8, #t9) in #t9;
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this.dart
index 024d1cc..f1f28c4 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this.dart
@@ -23,18 +23,38 @@
 
   void test() {
     /*@target=Test::member*/ member = /*@ typeArgs=B* */ f();
-    /*@target=Test::member*/ member ??= /*@ typeArgs=B* */ f();
+
+    /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
     /*@target=Test::member*/ member += /*@ typeArgs=dynamic */ f();
+
     /*@target=Test::member*/ member *= /*@ typeArgs=dynamic */ f();
+
     /*@target=Test::member*/ member &= /*@ typeArgs=dynamic */ f();
+
     -- /*@target=Test::member*/ member;
+
     /*@target=Test::member*/ member--;
-    var /*@ type=B* */ v1 = /*@target=Test::member*/ member = /*@ typeArgs=B* */ f();
-    var /*@ type=B* */ v2 = /*@target=Test::member*/ member ??= /*@ typeArgs=B* */ f();
-    var /*@ type=A* */ v3 = /*@target=Test::member*/ member += /*@ typeArgs=dynamic */ f();
-    var /*@ type=B* */ v4 = /*@target=Test::member*/ member *= /*@ typeArgs=dynamic */ f();
-    var /*@ type=C* */ v5 = /*@target=Test::member*/ member &= /*@ typeArgs=dynamic */ f();
+
+    var /*@ type=B* */ v1 = /*@target=Test::member*/ member =
+        /*@ typeArgs=B* */ f();
+
+    var /*@ type=B* */ v2 = /*@target=Test::member*/ /*@target=Test::member*/
+        member
+            /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
+    var /*@ type=A* */ v3 = /*@target=Test::member*/ member +=
+        /*@ typeArgs=dynamic */ f();
+
+    var /*@ type=B* */ v4 = /*@target=Test::member*/ member *=
+        /*@ typeArgs=dynamic */ f();
+
+    var /*@ type=C* */ v5 = /*@target=Test::member*/ member &=
+        /*@ typeArgs=dynamic */ f();
+
     var /*@ type=B* */ v6 = -- /*@target=Test::member*/ member;
+
     var /*@ type=B* */ v7 = /*@target=Test::member*/ member--;
   }
 }
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this_upwards.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this_upwards.dart
index 51356c8..cfabd2b 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this_upwards.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_implicit_this_upwards.dart
@@ -14,12 +14,21 @@
 
   void test() {
     var /*@ type=int* */ v1 = /*@target=Test1::t*/ t = getInt();
+
     var /*@ type=num* */ v2 = /*@target=Test1::t*/ t = getNum();
-    var /*@ type=int* */ v4 = /*@target=Test1::t*/ t ??= getInt();
-    var /*@ type=num* */ v5 = /*@target=Test1::t*/ t ??= getNum();
+
+    var /*@ type=int* */ v4 = /*@target=Test1::t*/ /*@target=Test1::t*/ t
+        /*@ target=num::== */ ??= getInt();
+
+    var /*@ type=num* */ v5 = /*@target=Test1::t*/ /*@target=Test1::t*/ t
+        /*@ target=num::== */ ??= getNum();
+
     var /*@ type=int* */ v7 = /*@target=Test1::t*/ t += getInt();
+
     var /*@ type=num* */ v8 = /*@target=Test1::t*/ t += getNum();
+
     var /*@ type=int* */ v10 = ++ /*@target=Test1::t*/ t;
+
     var /*@ type=int* */ v11 = /*@target=Test1::t*/ t++;
   }
 }
@@ -29,15 +38,28 @@
 
   void test() {
     var /*@ type=int* */ v1 = /*@target=Test2::t*/ t = getInt();
+
     var /*@ type=num* */ v2 = /*@target=Test2::t*/ t = getNum();
+
     var /*@ type=double* */ v3 = /*@target=Test2::t*/ t = getDouble();
-    var /*@ type=num* */ v4 = /*@target=Test2::t*/ t ??= getInt();
-    var /*@ type=num* */ v5 = /*@target=Test2::t*/ t ??= getNum();
-    var /*@ type=num* */ v6 = /*@target=Test2::t*/ t ??= getDouble();
+
+    var /*@ type=num* */ v4 = /*@target=Test2::t*/ /*@target=Test2::t*/ t
+        /*@ target=num::== */ ??= getInt();
+
+    var /*@ type=num* */ v5 = /*@target=Test2::t*/ /*@target=Test2::t*/ t
+        /*@ target=num::== */ ??= getNum();
+
+    var /*@ type=num* */ v6 = /*@target=Test2::t*/ /*@target=Test2::t*/ t
+        /*@ target=num::== */ ??= getDouble();
+
     var /*@ type=num* */ v7 = /*@target=Test2::t*/ t += getInt();
+
     var /*@ type=num* */ v8 = /*@target=Test2::t*/ t += getNum();
+
     var /*@ type=num* */ v9 = /*@target=Test2::t*/ t += getDouble();
+
     var /*@ type=num* */ v10 = ++ /*@target=Test2::t*/ t;
+
     var /*@ type=num* */ v11 = /*@target=Test2::t*/ t++;
   }
 }
@@ -47,13 +69,23 @@
 
   void test3() {
     var /*@ type=num* */ v2 = /*@target=Test3::t*/ t = getNum();
+
     var /*@ type=double* */ v3 = /*@target=Test3::t*/ t = getDouble();
-    var /*@ type=num* */ v5 = /*@target=Test3::t*/ t ??= getNum();
-    var /*@ type=double* */ v6 = /*@target=Test3::t*/ t ??= getDouble();
+
+    var /*@ type=num* */ v5 = /*@target=Test3::t*/ /*@target=Test3::t*/ t
+        /*@ target=num::== */ ??= getNum();
+
+    var /*@ type=double* */ v6 = /*@target=Test3::t*/ /*@target=Test3::t*/ t
+        /*@ target=num::== */ ??= getDouble();
+
     var /*@ type=double* */ v7 = /*@target=Test3::t*/ t += getInt();
+
     var /*@ type=double* */ v8 = /*@target=Test3::t*/ t += getNum();
+
     var /*@ type=double* */ v9 = /*@target=Test3::t*/ t += getDouble();
+
     var /*@ type=double* */ v10 = ++ /*@target=Test3::t*/ t;
+
     var /*@ type=double* */ v11 = /*@target=Test3::t*/ t++;
   }
 }
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart
index 8271a08..4d3a249 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart
@@ -26,28 +26,60 @@
 
   void test() {
     Test t = /*@ typeArgs=Test* */ f();
-    t /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()] = /*@ typeArgs=B* */ f();
-    t /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()] ??= /*@ typeArgs=B* */ f();
+
     t /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] += /*@ typeArgs=dynamic */ f();
-    t /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] *= /*@ typeArgs=dynamic */ f();
-    t /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] &= /*@ typeArgs=dynamic */ f();
-    --t /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()];
-    t /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()]--;
+        /*@ typeArgs=Index* */ f()] = /*@ typeArgs=B* */ f();
+
+    t /*@target=Test::[]*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@target=Object::==*/ /*@target=Test::[]=*/ ??= /*@ typeArgs=B* */ f();
+
+    t /*@target=Test::[]*/ /*@target=Test::[]=*/ [/*@ typeArgs=Index* */ f()]
+        /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+    t /*@target=Test::[]*/ /*@target=Test::[]=*/ [/*@ typeArgs=Index* */ f()]
+        /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+    t /*@target=Test::[]*/ /*@target=Test::[]=*/ [/*@ typeArgs=Index* */ f()]
+        /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+    t /*@target=Test::[]*/ [/*@ typeArgs=Index* */ f()];
+
+    /*@ target=B::- */ --t
+        /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+        /*@ typeArgs=Index* */ f()];
+
+    t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+        /*@ typeArgs=Index* */ f()] /*@ target=B::- */ --;
+
     var /*@ type=B* */ v1 = t /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] = /*@ typeArgs=B* */ f();
-    var /*@ type=B* */ v2 = t /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] ??= /*@ typeArgs=B* */ f();
-    var /*@ type=A* */ v3 = t /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] += /*@ typeArgs=dynamic */ f();
-    var /*@ type=B* */ v4 = t /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] *= /*@ typeArgs=dynamic */ f();
-    var /*@ type=C* */ v5 = t /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] &= /*@ typeArgs=dynamic */ f();
-    var /*@ type=B* */ v6 = --t /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()];
-    var /*@ type=B* */ v7 = t /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()]--;
+        /*@ typeArgs=Index* */ f()] = /*@ typeArgs=B* */ f();
+
+    var /*@ type=B* */ v2 = t /*@target=Test::[]*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@target=Object::==*/ /*@target=Test::[]=*/ ??= /*@ typeArgs=B* */ f();
+
+    var /*@ type=A* */ v3 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+    var /*@ type=B* */ v4 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+    var /*@ type=C* */ v5 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+    var /*@ type=B* */ v6 = t /*@target=Test::[]*/ [/*@ typeArgs=Index* */ f()];
+
+    var /*@ type=B* */ v7 =
+        /*@ target=B::- */ --t
+            /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()];
+
+    var /*@ type=B* */ v8 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+        /*@ typeArgs=Index* */ f()] /*@ target=B::- */ --;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart.strong.expect
index a86cc01..79ba7a1 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart.strong.expect
@@ -39,20 +39,22 @@
   operator []=(self::Index* i, self::B* v) → void {}
   method test() → void {
     self::Test* t = self::f<self::Test*>();
-    t.{self::Test::[]=}(self::f<dynamic>() as{TypeError} self::Index*, self::f<self::B*>());
-    let final self::Test* #t1 = t in let final dynamic #t2 = self::f<dynamic>() in #t1.{self::Test::[]}(#t2 as{TypeError} self::Index*).{core::Object::==}(null) ?{self::B*} let final self::B* #t3 = self::f<self::B*>() in let final void #t4 = #t1.{self::Test::[]=}(#t2 as{TypeError} self::Index*, #t3) in #t3 : null;
-    let final self::Test* #t5 = t in let final dynamic #t6 = self::f<dynamic>() in #t5.{self::Test::[]=}(#t6 as{TypeError} self::Index*, #t5.{self::Test::[]}(#t6 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*);
-    let final self::Test* #t7 = t in let final dynamic #t8 = self::f<dynamic>() in #t7.{self::Test::[]=}(#t8 as{TypeError} self::Index*, #t7.{self::Test::[]}(#t8 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*));
-    let final self::Test* #t9 = t in let final dynamic #t10 = self::f<dynamic>() in #t9.{self::Test::[]=}(#t10 as{TypeError} self::Index*, #t9.{self::Test::[]}(#t10 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*));
-    let final self::Test* #t11 = t in let final dynamic #t12 = self::f<dynamic>() in let final self::B* #t13 = #t11.{self::Test::[]}(#t12 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t14 = #t11.{self::Test::[]=}(#t12 as{TypeError} self::Index*, #t13) in #t13;
-    let final self::Test* #t15 = t in let final dynamic #t16 = self::f<dynamic>() in #t15.{self::Test::[]=}(#t16 as{TypeError} self::Index*, #t15.{self::Test::[]}(#t16 as{TypeError} self::Index*).{self::B::-}(1));
-    self::B* v1 = let final self::Test* #t17 = t in let final dynamic #t18 = self::f<dynamic>() in let final self::B* #t19 = self::f<self::B*>() in let final void #t20 = #t17.{self::Test::[]=}(#t18 as{TypeError} self::Index*, #t19) in #t19;
-    self::B* v2 = let final self::Test* #t21 = t in let final dynamic #t22 = self::f<dynamic>() in let final self::B* #t23 = #t21.{self::Test::[]}(#t22 as{TypeError} self::Index*) in #t23.{core::Object::==}(null) ?{self::B*} let final self::B* #t24 = self::f<self::B*>() in let final void #t25 = #t21.{self::Test::[]=}(#t22 as{TypeError} self::Index*, #t24) in #t24 : #t23;
-    self::A* v3 = let final self::Test* #t26 = t in let final dynamic #t27 = self::f<dynamic>() in let final self::A* #t28 = #t26.{self::Test::[]}(#t27 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B* in let final void #t29 = #t26.{self::Test::[]=}(#t27 as{TypeError} self::Index*, #t28) in #t28;
-    self::B* v4 = let final self::Test* #t30 = t in let final dynamic #t31 = self::f<dynamic>() in let final self::B* #t32 = #t30.{self::Test::[]}(#t31 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*) in let final void #t33 = #t30.{self::Test::[]=}(#t31 as{TypeError} self::Index*, #t32) in #t32;
-    self::C* v5 = let final self::Test* #t34 = t in let final dynamic #t35 = self::f<dynamic>() in let final self::C* #t36 = #t34.{self::Test::[]}(#t35 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*) in let final void #t37 = #t34.{self::Test::[]=}(#t35 as{TypeError} self::Index*, #t36) in #t36;
-    self::B* v6 = let final self::Test* #t38 = t in let final dynamic #t39 = self::f<dynamic>() in let final self::B* #t40 = #t38.{self::Test::[]}(#t39 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t41 = #t38.{self::Test::[]=}(#t39 as{TypeError} self::Index*, #t40) in #t40;
-    self::B* v7 = let final self::Test* #t42 = t in let final dynamic #t43 = self::f<dynamic>() in let final self::B* #t44 = #t42.{self::Test::[]}(#t43 as{TypeError} self::Index*) in let final void #t45 = #t42.{self::Test::[]=}(#t43 as{TypeError} self::Index*, #t44.{self::B::-}(1)) in #t44;
+    t.{self::Test::[]=}(self::f<self::Index*>(), self::f<self::B*>());
+    let final self::Test* #t1 = t in let final self::Index* #t2 = self::f<self::Index*>() in #t1.{self::Test::[]}(#t2).{core::Object::==}(null) ?{self::B*} #t1.{self::Test::[]=}(#t2, self::f<self::B*>()) : null;
+    let final self::Test* #t3 = t in let final self::Index* #t4 = self::f<self::Index*>() in #t3.{self::Test::[]=}(#t4, #t3.{self::Test::[]}(#t4).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*);
+    let final self::Test* #t5 = t in let final self::Index* #t6 = self::f<self::Index*>() in #t5.{self::Test::[]=}(#t6, #t5.{self::Test::[]}(#t6).{self::B::*}(self::f<self::B*>()));
+    let final self::Test* #t7 = t in let final self::Index* #t8 = self::f<self::Index*>() in #t7.{self::Test::[]=}(#t8, #t7.{self::Test::[]}(#t8).{self::B::&}(self::f<self::A*>()));
+    t.{self::Test::[]}(self::f<self::Index*>());
+    let final self::Test* #t9 = t in let final self::Index* #t10 = self::f<self::Index*>() in let final self::B* #t11 = #t9.{self::Test::[]}(#t10).{self::B::-}(1) in let final void #t12 = #t9.{self::Test::[]=}(#t10, #t11) in #t11;
+    let final self::Test* #t13 = t in let final self::Index* #t14 = self::f<self::Index*>() in #t13.{self::Test::[]=}(#t14, #t13.{self::Test::[]}(#t14).{self::B::-}(1));
+    self::B* v1 = let final self::Test* #t15 = t in let final self::Index* #t16 = self::f<self::Index*>() in let final self::B* #t17 = self::f<self::B*>() in let final void #t18 = #t15.{self::Test::[]=}(#t16, #t17) in #t17;
+    self::B* v2 = let final self::Test* #t19 = t in let final self::Index* #t20 = self::f<self::Index*>() in let final self::B* #t21 = #t19.{self::Test::[]}(#t20) in #t21.{core::Object::==}(null) ?{self::B*} let final self::B* #t22 = self::f<self::B*>() in let final void #t23 = #t19.{self::Test::[]=}(#t20, #t22) in #t22 : #t21;
+    self::A* v3 = let final self::Test* #t24 = t in let final self::Index* #t25 = self::f<self::Index*>() in let final self::A* #t26 = #t24.{self::Test::[]}(#t25).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t27 = #t24.{self::Test::[]=}(#t25, #t26) in #t26;
+    self::B* v4 = let final self::Test* #t28 = t in let final self::Index* #t29 = self::f<self::Index*>() in let final self::B* #t30 = #t28.{self::Test::[]}(#t29).{self::B::*}(self::f<self::B*>()) in let final void #t31 = #t28.{self::Test::[]=}(#t29, #t30) in #t30;
+    self::C* v5 = let final self::Test* #t32 = t in let final self::Index* #t33 = self::f<self::Index*>() in let final self::C* #t34 = #t32.{self::Test::[]}(#t33).{self::B::&}(self::f<self::A*>()) in let final void #t35 = #t32.{self::Test::[]=}(#t33, #t34) in #t34;
+    self::B* v6 = t.{self::Test::[]}(self::f<self::Index*>());
+    self::B* v7 = let final self::Test* #t36 = t in let final self::Index* #t37 = self::f<self::Index*>() in let final self::B* #t38 = #t36.{self::Test::[]}(#t37).{self::B::-}(1) in let final void #t39 = #t36.{self::Test::[]=}(#t37, #t38) in #t38;
+    self::B* v8 = let final self::Test* #t40 = t in let final self::Index* #t41 = self::f<self::Index*>() in let final self::B* #t42 = #t40.{self::Test::[]}(#t41) in let final void #t43 = #t40.{self::Test::[]=}(#t41, #t42.{self::B::-}(1)) in #t42;
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart.strong.transformed.expect
index a86cc01..79ba7a1 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_full.dart.strong.transformed.expect
@@ -39,20 +39,22 @@
   operator []=(self::Index* i, self::B* v) → void {}
   method test() → void {
     self::Test* t = self::f<self::Test*>();
-    t.{self::Test::[]=}(self::f<dynamic>() as{TypeError} self::Index*, self::f<self::B*>());
-    let final self::Test* #t1 = t in let final dynamic #t2 = self::f<dynamic>() in #t1.{self::Test::[]}(#t2 as{TypeError} self::Index*).{core::Object::==}(null) ?{self::B*} let final self::B* #t3 = self::f<self::B*>() in let final void #t4 = #t1.{self::Test::[]=}(#t2 as{TypeError} self::Index*, #t3) in #t3 : null;
-    let final self::Test* #t5 = t in let final dynamic #t6 = self::f<dynamic>() in #t5.{self::Test::[]=}(#t6 as{TypeError} self::Index*, #t5.{self::Test::[]}(#t6 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*);
-    let final self::Test* #t7 = t in let final dynamic #t8 = self::f<dynamic>() in #t7.{self::Test::[]=}(#t8 as{TypeError} self::Index*, #t7.{self::Test::[]}(#t8 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*));
-    let final self::Test* #t9 = t in let final dynamic #t10 = self::f<dynamic>() in #t9.{self::Test::[]=}(#t10 as{TypeError} self::Index*, #t9.{self::Test::[]}(#t10 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*));
-    let final self::Test* #t11 = t in let final dynamic #t12 = self::f<dynamic>() in let final self::B* #t13 = #t11.{self::Test::[]}(#t12 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t14 = #t11.{self::Test::[]=}(#t12 as{TypeError} self::Index*, #t13) in #t13;
-    let final self::Test* #t15 = t in let final dynamic #t16 = self::f<dynamic>() in #t15.{self::Test::[]=}(#t16 as{TypeError} self::Index*, #t15.{self::Test::[]}(#t16 as{TypeError} self::Index*).{self::B::-}(1));
-    self::B* v1 = let final self::Test* #t17 = t in let final dynamic #t18 = self::f<dynamic>() in let final self::B* #t19 = self::f<self::B*>() in let final void #t20 = #t17.{self::Test::[]=}(#t18 as{TypeError} self::Index*, #t19) in #t19;
-    self::B* v2 = let final self::Test* #t21 = t in let final dynamic #t22 = self::f<dynamic>() in let final self::B* #t23 = #t21.{self::Test::[]}(#t22 as{TypeError} self::Index*) in #t23.{core::Object::==}(null) ?{self::B*} let final self::B* #t24 = self::f<self::B*>() in let final void #t25 = #t21.{self::Test::[]=}(#t22 as{TypeError} self::Index*, #t24) in #t24 : #t23;
-    self::A* v3 = let final self::Test* #t26 = t in let final dynamic #t27 = self::f<dynamic>() in let final self::A* #t28 = #t26.{self::Test::[]}(#t27 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B* in let final void #t29 = #t26.{self::Test::[]=}(#t27 as{TypeError} self::Index*, #t28) in #t28;
-    self::B* v4 = let final self::Test* #t30 = t in let final dynamic #t31 = self::f<dynamic>() in let final self::B* #t32 = #t30.{self::Test::[]}(#t31 as{TypeError} self::Index*).{self::B::*}(self::f<dynamic>() as{TypeError} self::B*) in let final void #t33 = #t30.{self::Test::[]=}(#t31 as{TypeError} self::Index*, #t32) in #t32;
-    self::C* v5 = let final self::Test* #t34 = t in let final dynamic #t35 = self::f<dynamic>() in let final self::C* #t36 = #t34.{self::Test::[]}(#t35 as{TypeError} self::Index*).{self::B::&}(self::f<dynamic>() as{TypeError} self::A*) in let final void #t37 = #t34.{self::Test::[]=}(#t35 as{TypeError} self::Index*, #t36) in #t36;
-    self::B* v6 = let final self::Test* #t38 = t in let final dynamic #t39 = self::f<dynamic>() in let final self::B* #t40 = #t38.{self::Test::[]}(#t39 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t41 = #t38.{self::Test::[]=}(#t39 as{TypeError} self::Index*, #t40) in #t40;
-    self::B* v7 = let final self::Test* #t42 = t in let final dynamic #t43 = self::f<dynamic>() in let final self::B* #t44 = #t42.{self::Test::[]}(#t43 as{TypeError} self::Index*) in let final void #t45 = #t42.{self::Test::[]=}(#t43 as{TypeError} self::Index*, #t44.{self::B::-}(1)) in #t44;
+    t.{self::Test::[]=}(self::f<self::Index*>(), self::f<self::B*>());
+    let final self::Test* #t1 = t in let final self::Index* #t2 = self::f<self::Index*>() in #t1.{self::Test::[]}(#t2).{core::Object::==}(null) ?{self::B*} #t1.{self::Test::[]=}(#t2, self::f<self::B*>()) : null;
+    let final self::Test* #t3 = t in let final self::Index* #t4 = self::f<self::Index*>() in #t3.{self::Test::[]=}(#t4, #t3.{self::Test::[]}(#t4).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*);
+    let final self::Test* #t5 = t in let final self::Index* #t6 = self::f<self::Index*>() in #t5.{self::Test::[]=}(#t6, #t5.{self::Test::[]}(#t6).{self::B::*}(self::f<self::B*>()));
+    let final self::Test* #t7 = t in let final self::Index* #t8 = self::f<self::Index*>() in #t7.{self::Test::[]=}(#t8, #t7.{self::Test::[]}(#t8).{self::B::&}(self::f<self::A*>()));
+    t.{self::Test::[]}(self::f<self::Index*>());
+    let final self::Test* #t9 = t in let final self::Index* #t10 = self::f<self::Index*>() in let final self::B* #t11 = #t9.{self::Test::[]}(#t10).{self::B::-}(1) in let final void #t12 = #t9.{self::Test::[]=}(#t10, #t11) in #t11;
+    let final self::Test* #t13 = t in let final self::Index* #t14 = self::f<self::Index*>() in #t13.{self::Test::[]=}(#t14, #t13.{self::Test::[]}(#t14).{self::B::-}(1));
+    self::B* v1 = let final self::Test* #t15 = t in let final self::Index* #t16 = self::f<self::Index*>() in let final self::B* #t17 = self::f<self::B*>() in let final void #t18 = #t15.{self::Test::[]=}(#t16, #t17) in #t17;
+    self::B* v2 = let final self::Test* #t19 = t in let final self::Index* #t20 = self::f<self::Index*>() in let final self::B* #t21 = #t19.{self::Test::[]}(#t20) in #t21.{core::Object::==}(null) ?{self::B*} let final self::B* #t22 = self::f<self::B*>() in let final void #t23 = #t19.{self::Test::[]=}(#t20, #t22) in #t22 : #t21;
+    self::A* v3 = let final self::Test* #t24 = t in let final self::Index* #t25 = self::f<self::Index*>() in let final self::A* #t26 = #t24.{self::Test::[]}(#t25).{self::B::+}(self::f<self::C*>()) as{TypeError} self::B* in let final void #t27 = #t24.{self::Test::[]=}(#t25, #t26) in #t26;
+    self::B* v4 = let final self::Test* #t28 = t in let final self::Index* #t29 = self::f<self::Index*>() in let final self::B* #t30 = #t28.{self::Test::[]}(#t29).{self::B::*}(self::f<self::B*>()) in let final void #t31 = #t28.{self::Test::[]=}(#t29, #t30) in #t30;
+    self::C* v5 = let final self::Test* #t32 = t in let final self::Index* #t33 = self::f<self::Index*>() in let final self::C* #t34 = #t32.{self::Test::[]}(#t33).{self::B::&}(self::f<self::A*>()) in let final void #t35 = #t32.{self::Test::[]=}(#t33, #t34) in #t34;
+    self::B* v6 = t.{self::Test::[]}(self::f<self::Index*>());
+    self::B* v7 = let final self::Test* #t36 = t in let final self::Index* #t37 = self::f<self::Index*>() in let final self::B* #t38 = #t36.{self::Test::[]}(#t37).{self::B::-}(1) in let final void #t39 = #t36.{self::Test::[]=}(#t37, #t38) in #t38;
+    self::B* v8 = let final self::Test* #t40 = t in let final self::Index* #t41 = self::f<self::Index*>() in let final self::B* #t42 = #t40.{self::Test::[]}(#t41) in let final void #t43 = #t40.{self::Test::[]=}(#t41, #t42.{self::B::-}(1)) in #t42;
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart
index 6857ea2..4f4b0ba 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart
@@ -33,20 +33,40 @@
 
   void test() {
     Test t = /*@ typeArgs=Test* */ f();
-    t /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()] = /*@ typeArgs=A* */ f();
-    t /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()] ??= /*@ typeArgs=A* */ f();
+
     t /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] += /*@ typeArgs=dynamic */ f();
-    --t /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()];
-    t /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()]--;
+        /*@ typeArgs=Index* */ f()] = /*@ typeArgs=A* */ f();
+
+    t /*@target=Test::[]*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@target=Object::==*/ /*@target=Test::[]=*/ ??= /*@ typeArgs=A* */ f();
+
+    t /*@target=Test::[]*/ /*@target=Test::[]=*/ [/*@ typeArgs=Index* */ f()]
+        /*@ target=B::+ */ += /*@ typeArgs=E* */ f();
+
+    /*@ target=B::- */ --t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+        /*@ typeArgs=Index* */ f()];
+
+    t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+        /*@ typeArgs=Index* */ f()] /*@ target=B::- */ --;
+
     var /*@ type=A* */ v1 = t /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] = /*@ typeArgs=A* */ f();
-    var /*@ type=A* */ v2 = t /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] ??= /*@ typeArgs=A* */ f();
-    var /*@ type=D* */ v3 = t /*@target=Test::[]=*/ [
-        /*@ typeArgs=dynamic */ f()] += /*@ typeArgs=dynamic */ f();
-    var /*@ type=D* */ v4 = --t /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()];
-    var /*@ type=B* */ v5 = t /*@target=Test::[]=*/ [/*@ typeArgs=dynamic */ f()]--;
+        /*@ typeArgs=Index* */ f()] = /*@ typeArgs=A* */ f();
+
+    var /*@ type=A* */ v2 = t /*@target=Test::[]*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@target=Object::==*/ /*@target=Test::[]=*/ ??= /*@ typeArgs=A* */ f();
+
+    var /*@ type=D* */ v3 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()]
+        /*@ target=B::+ */ += /*@ typeArgs=E* */ f();
+
+    var /*@ type=D* */ v4 =
+        /*@ target=B::- */ --t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+            /*@ typeArgs=Index* */ f()];
+
+    var /*@ type=B* */ v5 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+        /*@ typeArgs=Index* */ f()] /*@ target=B::- */ --;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart.strong.expect
index cde8b4e..9bba684 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart.strong.expect
@@ -54,16 +54,16 @@
   operator []=(self::Index* i, self::A* v) → void {}
   method test() → void {
     self::Test* t = self::f<self::Test*>();
-    t.{self::Test::[]=}(self::f<dynamic>() as{TypeError} self::Index*, self::f<self::A*>());
-    let final self::Test* #t1 = t in let final dynamic #t2 = self::f<dynamic>() in #t1.{self::Test::[]}(#t2 as{TypeError} self::Index*).{core::Object::==}(null) ?{self::A*} let final self::A* #t3 = self::f<self::A*>() in let final void #t4 = #t1.{self::Test::[]=}(#t2 as{TypeError} self::Index*, #t3) in #t3 : null;
-    let final self::Test* #t5 = t in let final dynamic #t6 = self::f<dynamic>() in #t5.{self::Test::[]=}(#t6 as{TypeError} self::Index*, #t5.{self::Test::[]}(#t6 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::E*));
-    let final self::Test* #t7 = t in let final dynamic #t8 = self::f<dynamic>() in let final self::D* #t9 = #t7.{self::Test::[]}(#t8 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t10 = #t7.{self::Test::[]=}(#t8 as{TypeError} self::Index*, #t9) in #t9;
-    let final self::Test* #t11 = t in let final dynamic #t12 = self::f<dynamic>() in #t11.{self::Test::[]=}(#t12 as{TypeError} self::Index*, #t11.{self::Test::[]}(#t12 as{TypeError} self::Index*).{self::B::-}(1));
-    self::A* v1 = let final self::Test* #t13 = t in let final dynamic #t14 = self::f<dynamic>() in let final self::A* #t15 = self::f<self::A*>() in let final void #t16 = #t13.{self::Test::[]=}(#t14 as{TypeError} self::Index*, #t15) in #t15;
-    self::A* v2 = let final self::Test* #t17 = t in let final dynamic #t18 = self::f<dynamic>() in let final self::B* #t19 = #t17.{self::Test::[]}(#t18 as{TypeError} self::Index*) in #t19.{core::Object::==}(null) ?{self::A*} let final self::A* #t20 = self::f<self::A*>() in let final void #t21 = #t17.{self::Test::[]=}(#t18 as{TypeError} self::Index*, #t20) in #t20 : #t19;
-    self::D* v3 = let final self::Test* #t22 = t in let final dynamic #t23 = self::f<dynamic>() in let final self::D* #t24 = #t22.{self::Test::[]}(#t23 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::E*) in let final void #t25 = #t22.{self::Test::[]=}(#t23 as{TypeError} self::Index*, #t24) in #t24;
-    self::D* v4 = let final self::Test* #t26 = t in let final dynamic #t27 = self::f<dynamic>() in let final self::D* #t28 = #t26.{self::Test::[]}(#t27 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t29 = #t26.{self::Test::[]=}(#t27 as{TypeError} self::Index*, #t28) in #t28;
-    self::B* v5 = let final self::Test* #t30 = t in let final dynamic #t31 = self::f<dynamic>() in let final self::B* #t32 = #t30.{self::Test::[]}(#t31 as{TypeError} self::Index*) in let final void #t33 = #t30.{self::Test::[]=}(#t31 as{TypeError} self::Index*, #t32.{self::B::-}(1)) in #t32;
+    t.{self::Test::[]=}(self::f<self::Index*>(), self::f<self::A*>());
+    let final self::Test* #t1 = t in let final self::Index* #t2 = self::f<self::Index*>() in #t1.{self::Test::[]}(#t2).{core::Object::==}(null) ?{self::A*} #t1.{self::Test::[]=}(#t2, self::f<self::A*>()) : null;
+    let final self::Test* #t3 = t in let final self::Index* #t4 = self::f<self::Index*>() in #t3.{self::Test::[]=}(#t4, #t3.{self::Test::[]}(#t4).{self::B::+}(self::f<self::E*>()));
+    let final self::Test* #t5 = t in let final self::Index* #t6 = self::f<self::Index*>() in let final self::D* #t7 = #t5.{self::Test::[]}(#t6).{self::B::-}(1) in let final void #t8 = #t5.{self::Test::[]=}(#t6, #t7) in #t7;
+    let final self::Test* #t9 = t in let final self::Index* #t10 = self::f<self::Index*>() in #t9.{self::Test::[]=}(#t10, #t9.{self::Test::[]}(#t10).{self::B::-}(1));
+    self::A* v1 = let final self::Test* #t11 = t in let final self::Index* #t12 = self::f<self::Index*>() in let final self::A* #t13 = self::f<self::A*>() in let final void #t14 = #t11.{self::Test::[]=}(#t12, #t13) in #t13;
+    self::A* v2 = let final self::Test* #t15 = t in let final self::Index* #t16 = self::f<self::Index*>() in let final self::B* #t17 = #t15.{self::Test::[]}(#t16) in #t17.{core::Object::==}(null) ?{self::A*} let final self::A* #t18 = self::f<self::A*>() in let final void #t19 = #t15.{self::Test::[]=}(#t16, #t18) in #t18 : #t17;
+    self::D* v3 = let final self::Test* #t20 = t in let final self::Index* #t21 = self::f<self::Index*>() in let final self::D* #t22 = #t20.{self::Test::[]}(#t21).{self::B::+}(self::f<self::E*>()) in let final void #t23 = #t20.{self::Test::[]=}(#t21, #t22) in #t22;
+    self::D* v4 = let final self::Test* #t24 = t in let final self::Index* #t25 = self::f<self::Index*>() in let final self::D* #t26 = #t24.{self::Test::[]}(#t25).{self::B::-}(1) in let final void #t27 = #t24.{self::Test::[]=}(#t25, #t26) in #t26;
+    self::B* v5 = let final self::Test* #t28 = t in let final self::Index* #t29 = self::f<self::Index*>() in let final self::B* #t30 = #t28.{self::Test::[]}(#t29) in let final void #t31 = #t28.{self::Test::[]=}(#t29, #t30.{self::B::-}(1)) in #t30;
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart.strong.transformed.expect
index cde8b4e..9bba684 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_set_vs_get.dart.strong.transformed.expect
@@ -54,16 +54,16 @@
   operator []=(self::Index* i, self::A* v) → void {}
   method test() → void {
     self::Test* t = self::f<self::Test*>();
-    t.{self::Test::[]=}(self::f<dynamic>() as{TypeError} self::Index*, self::f<self::A*>());
-    let final self::Test* #t1 = t in let final dynamic #t2 = self::f<dynamic>() in #t1.{self::Test::[]}(#t2 as{TypeError} self::Index*).{core::Object::==}(null) ?{self::A*} let final self::A* #t3 = self::f<self::A*>() in let final void #t4 = #t1.{self::Test::[]=}(#t2 as{TypeError} self::Index*, #t3) in #t3 : null;
-    let final self::Test* #t5 = t in let final dynamic #t6 = self::f<dynamic>() in #t5.{self::Test::[]=}(#t6 as{TypeError} self::Index*, #t5.{self::Test::[]}(#t6 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::E*));
-    let final self::Test* #t7 = t in let final dynamic #t8 = self::f<dynamic>() in let final self::D* #t9 = #t7.{self::Test::[]}(#t8 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t10 = #t7.{self::Test::[]=}(#t8 as{TypeError} self::Index*, #t9) in #t9;
-    let final self::Test* #t11 = t in let final dynamic #t12 = self::f<dynamic>() in #t11.{self::Test::[]=}(#t12 as{TypeError} self::Index*, #t11.{self::Test::[]}(#t12 as{TypeError} self::Index*).{self::B::-}(1));
-    self::A* v1 = let final self::Test* #t13 = t in let final dynamic #t14 = self::f<dynamic>() in let final self::A* #t15 = self::f<self::A*>() in let final void #t16 = #t13.{self::Test::[]=}(#t14 as{TypeError} self::Index*, #t15) in #t15;
-    self::A* v2 = let final self::Test* #t17 = t in let final dynamic #t18 = self::f<dynamic>() in let final self::B* #t19 = #t17.{self::Test::[]}(#t18 as{TypeError} self::Index*) in #t19.{core::Object::==}(null) ?{self::A*} let final self::A* #t20 = self::f<self::A*>() in let final void #t21 = #t17.{self::Test::[]=}(#t18 as{TypeError} self::Index*, #t20) in #t20 : #t19;
-    self::D* v3 = let final self::Test* #t22 = t in let final dynamic #t23 = self::f<dynamic>() in let final self::D* #t24 = #t22.{self::Test::[]}(#t23 as{TypeError} self::Index*).{self::B::+}(self::f<dynamic>() as{TypeError} self::E*) in let final void #t25 = #t22.{self::Test::[]=}(#t23 as{TypeError} self::Index*, #t24) in #t24;
-    self::D* v4 = let final self::Test* #t26 = t in let final dynamic #t27 = self::f<dynamic>() in let final self::D* #t28 = #t26.{self::Test::[]}(#t27 as{TypeError} self::Index*).{self::B::-}(1) in let final void #t29 = #t26.{self::Test::[]=}(#t27 as{TypeError} self::Index*, #t28) in #t28;
-    self::B* v5 = let final self::Test* #t30 = t in let final dynamic #t31 = self::f<dynamic>() in let final self::B* #t32 = #t30.{self::Test::[]}(#t31 as{TypeError} self::Index*) in let final void #t33 = #t30.{self::Test::[]=}(#t31 as{TypeError} self::Index*, #t32.{self::B::-}(1)) in #t32;
+    t.{self::Test::[]=}(self::f<self::Index*>(), self::f<self::A*>());
+    let final self::Test* #t1 = t in let final self::Index* #t2 = self::f<self::Index*>() in #t1.{self::Test::[]}(#t2).{core::Object::==}(null) ?{self::A*} #t1.{self::Test::[]=}(#t2, self::f<self::A*>()) : null;
+    let final self::Test* #t3 = t in let final self::Index* #t4 = self::f<self::Index*>() in #t3.{self::Test::[]=}(#t4, #t3.{self::Test::[]}(#t4).{self::B::+}(self::f<self::E*>()));
+    let final self::Test* #t5 = t in let final self::Index* #t6 = self::f<self::Index*>() in let final self::D* #t7 = #t5.{self::Test::[]}(#t6).{self::B::-}(1) in let final void #t8 = #t5.{self::Test::[]=}(#t6, #t7) in #t7;
+    let final self::Test* #t9 = t in let final self::Index* #t10 = self::f<self::Index*>() in #t9.{self::Test::[]=}(#t10, #t9.{self::Test::[]}(#t10).{self::B::-}(1));
+    self::A* v1 = let final self::Test* #t11 = t in let final self::Index* #t12 = self::f<self::Index*>() in let final self::A* #t13 = self::f<self::A*>() in let final void #t14 = #t11.{self::Test::[]=}(#t12, #t13) in #t13;
+    self::A* v2 = let final self::Test* #t15 = t in let final self::Index* #t16 = self::f<self::Index*>() in let final self::B* #t17 = #t15.{self::Test::[]}(#t16) in #t17.{core::Object::==}(null) ?{self::A*} let final self::A* #t18 = self::f<self::A*>() in let final void #t19 = #t15.{self::Test::[]=}(#t16, #t18) in #t18 : #t17;
+    self::D* v3 = let final self::Test* #t20 = t in let final self::Index* #t21 = self::f<self::Index*>() in let final self::D* #t22 = #t20.{self::Test::[]}(#t21).{self::B::+}(self::f<self::E*>()) in let final void #t23 = #t20.{self::Test::[]=}(#t21, #t22) in #t22;
+    self::D* v4 = let final self::Test* #t24 = t in let final self::Index* #t25 = self::f<self::Index*>() in let final self::D* #t26 = #t24.{self::Test::[]}(#t25).{self::B::-}(1) in let final void #t27 = #t24.{self::Test::[]=}(#t25, #t26) in #t26;
+    self::B* v5 = let final self::Test* #t28 = t in let final self::Index* #t29 = self::f<self::Index*>() in let final self::B* #t30 = #t28.{self::Test::[]}(#t29) in let final void #t31 = #t28.{self::Test::[]=}(#t29, #t30.{self::B::-}(1)) in #t30;
   }
 }
 static method f<T extends core::Object* = dynamic>() → self::f::T*
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart
index 27c4248..dee0c7d 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart
@@ -16,113 +16,291 @@
 
 void test1(Test<int, int> t) {
   var /*@ type=int* */ v1 = t /*@target=Test::[]=*/ ['x'] = getInt();
+
   var /*@ type=num* */ v2 = t /*@target=Test::[]=*/ ['x'] = getNum();
-  var /*@ type=int* */ v4 = t /*@target=Test::[]=*/ ['x'] ??= getInt();
-  var /*@ type=num* */ v5 = t /*@target=Test::[]=*/ ['x'] ??= getNum();
-  var /*@ type=int* */ v7 = t /*@target=Test::[]=*/ ['x'] += getInt();
-  var /*@ type=num* */ v8 = t /*@target=Test::[]=*/ ['x'] += getNum();
-  var /*@ type=int* */ v10 = ++t /*@target=Test::[]=*/ ['x'];
-  var /*@ type=int* */ v11 = t /*@target=Test::[]=*/ ['x']++;
+
+  var /*@ type=int* */ v4 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getInt();
+
+  var /*@ type=num* */ v5 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getNum();
+
+  var /*@ type=int* */ v7 =
+      t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
+          getInt();
+
+  var /*@ type=num* */ v8 =
+      t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
+          getNum();
+
+  var /*@ type=int* */ v10 =
+      /*@ target=num::+ */ ++t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'];
+
+  var /*@ type=int* */ v11 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+      'x'] /*@ target=num::+ */ ++;
 }
 
 void test2(Test<int, num> t) {
   var /*@ type=int* */ v1 = t /*@target=Test::[]=*/ ['x'] = getInt();
+
   var /*@ type=num* */ v2 = t /*@target=Test::[]=*/ ['x'] = getNum();
+
   var /*@ type=double* */ v3 = t /*@target=Test::[]=*/ ['x'] = getDouble();
-  var /*@ type=int* */ v4 = t /*@target=Test::[]=*/ ['x'] ??= getInt();
-  var /*@ type=num* */ v5 = t /*@target=Test::[]=*/ ['x'] ??= getNum();
-  var /*@ type=num* */ v6 = t /*@target=Test::[]=*/ ['x'] ??= getDouble();
-  var /*@ type=int* */ v7 = t /*@target=Test::[]=*/ ['x'] += getInt();
-  var /*@ type=num* */ v8 = t /*@target=Test::[]=*/ ['x'] += getNum();
-  var /*@ type=double* */ v9 = t /*@target=Test::[]=*/ ['x'] += getDouble();
-  var /*@ type=int* */ v10 = ++t /*@target=Test::[]=*/ ['x'];
-  var /*@ type=int* */ v11 = t /*@target=Test::[]=*/ ['x']++;
+
+  var /*@ type=int* */ v4 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getInt();
+
+  var /*@ type=num* */ v5 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getNum();
+
+  var /*@ type=num* */ v6 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getDouble();
+
+  var /*@ type=int* */ v7 =
+      t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
+          getInt();
+
+  var /*@ type=num* */ v8 =
+      t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
+          getNum();
+
+  var /*@ type=double* */ v9 =
+      t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
+          getDouble();
+
+  var /*@ type=int* */ v10 =
+      /*@ target=num::+ */ ++t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'];
+
+  var /*@ type=int* */ v11 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+      'x'] /*@ target=num::+ */ ++;
 }
 
 void test3(Test<int, double> t) {
   var /*@ type=num* */ v2 = t /*@target=Test::[]=*/ ['x'] = getNum();
+
   var /*@ type=double* */ v3 = t /*@target=Test::[]=*/ ['x'] = getDouble();
-  var /*@ type=num* */ v5 = t /*@target=Test::[]=*/ ['x'] ??= getNum();
-  var /*@ type=num* */ v6 = t /*@target=Test::[]=*/ ['x'] ??= getDouble();
-  var /*@ type=int* */ v7 = t /*@target=Test::[]=*/ ['x'] += getInt();
-  var /*@ type=num* */ v8 = t /*@target=Test::[]=*/ ['x'] += getNum();
-  var /*@ type=double* */ v9 = t /*@target=Test::[]=*/ ['x'] += getDouble();
-  var /*@ type=int* */ v10 = ++t /*@target=Test::[]=*/ ['x'];
-  var /*@ type=int* */ v11 = t /*@target=Test::[]=*/ ['x']++;
+
+  var /*@ type=num* */ v5 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getNum();
+
+  var /*@ type=num* */ v6 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getDouble();
+
+  var /*@ type=int* */ v7 =
+      t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
+          getInt();
+
+  var /*@ type=num* */ v8 =
+      t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
+          getNum();
+
+  var /*@ type=double* */ v9 =
+      t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
+          getDouble();
+
+  var /*@ type=int* */ v10 =
+      /*@ target=num::+ */ ++t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'];
+
+  var /*@ type=int* */ v11 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+      'x'] /*@ target=num::+ */ ++;
 }
 
 void test4(Test<num, int> t) {
   var /*@ type=int* */ v1 = t /*@target=Test::[]=*/ ['x'] = getInt();
+
   var /*@ type=num* */ v2 = t /*@target=Test::[]=*/ ['x'] = getNum();
-  var /*@ type=num* */ v4 = t /*@target=Test::[]=*/ ['x'] ??= getInt();
-  var /*@ type=num* */ v5 = t /*@target=Test::[]=*/ ['x'] ??= getNum();
-  var /*@ type=num* */ v7 = t /*@target=Test::[]=*/ ['x'] += getInt();
-  var /*@ type=num* */ v8 = t /*@target=Test::[]=*/ ['x'] += getNum();
-  var /*@ type=num* */ v10 = ++t /*@target=Test::[]=*/ ['x'];
-  var /*@ type=num* */ v11 = t /*@target=Test::[]=*/ ['x']++;
+
+  var /*@ type=num* */ v4 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getInt();
+
+  var /*@ type=num* */ v5 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getNum();
+
+  var /*@ type=num* */ v7 =
+      t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
+          getInt();
+
+  var /*@ type=num* */ v8 =
+      t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
+          getNum();
+
+  var /*@ type=num* */ v10 =
+      /*@ target=num::+ */ ++t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'];
+
+  var /*@ type=num* */ v11 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+      'x'] /*@ target=num::+ */ ++;
 }
 
 void test5(Test<num, num> t) {
   var /*@ type=int* */ v1 = t /*@target=Test::[]=*/ ['x'] = getInt();
+
   var /*@ type=num* */ v2 = t /*@target=Test::[]=*/ ['x'] = getNum();
+
   var /*@ type=double* */ v3 = t /*@target=Test::[]=*/ ['x'] = getDouble();
-  var /*@ type=num* */ v4 = t /*@target=Test::[]=*/ ['x'] ??= getInt();
-  var /*@ type=num* */ v5 = t /*@target=Test::[]=*/ ['x'] ??= getNum();
-  var /*@ type=num* */ v6 = t /*@target=Test::[]=*/ ['x'] ??= getDouble();
-  var /*@ type=num* */ v7 = t /*@target=Test::[]=*/ ['x'] += getInt();
-  var /*@ type=num* */ v8 = t /*@target=Test::[]=*/ ['x'] += getNum();
-  var /*@ type=num* */ v9 = t /*@target=Test::[]=*/ ['x'] += getDouble();
-  var /*@ type=num* */ v10 = ++t /*@target=Test::[]=*/ ['x'];
-  var /*@ type=num* */ v11 = t /*@target=Test::[]=*/ ['x']++;
+
+  var /*@ type=num* */ v4 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getInt();
+
+  var /*@ type=num* */ v5 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getNum();
+
+  var /*@ type=num* */ v6 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getDouble();
+
+  var /*@ type=num* */ v7 =
+      t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
+          getInt();
+
+  var /*@ type=num* */ v8 =
+      t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
+          getNum();
+
+  var /*@ type=num* */ v9 =
+      t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
+          getDouble();
+
+  var /*@ type=num* */ v10 =
+      /*@ target=num::+ */ ++t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'];
+
+  var /*@ type=num* */ v11 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+      'x'] /*@ target=num::+ */ ++;
 }
 
 void test6(Test<num, double> t) {
   var /*@ type=num* */ v2 = t /*@target=Test::[]=*/ ['x'] = getNum();
+
   var /*@ type=double* */ v3 = t /*@target=Test::[]=*/ ['x'] = getDouble();
-  var /*@ type=num* */ v5 = t /*@target=Test::[]=*/ ['x'] ??= getNum();
-  var /*@ type=num* */ v6 = t /*@target=Test::[]=*/ ['x'] ??= getDouble();
-  var /*@ type=num* */ v7 = t /*@target=Test::[]=*/ ['x'] += getInt();
-  var /*@ type=num* */ v8 = t /*@target=Test::[]=*/ ['x'] += getNum();
-  var /*@ type=num* */ v9 = t /*@target=Test::[]=*/ ['x'] += getDouble();
-  var /*@ type=num* */ v10 = ++t /*@target=Test::[]=*/ ['x'];
-  var /*@ type=num* */ v11 = t /*@target=Test::[]=*/ ['x']++;
+
+  var /*@ type=num* */ v5 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getNum();
+
+  var /*@ type=num* */ v6 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getDouble();
+
+  var /*@ type=num* */ v7 =
+      t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
+          getInt();
+
+  var /*@ type=num* */ v8 =
+      t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
+          getNum();
+
+  var /*@ type=num* */ v9 =
+      t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
+          getDouble();
+
+  var /*@ type=num* */ v10 =
+      /*@ target=num::+ */ ++t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'];
+
+  var /*@ type=num* */ v11 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+      'x'] /*@ target=num::+ */ ++;
 }
 
 void test7(Test<double, int> t) {
   var /*@ type=int* */ v1 = t /*@target=Test::[]=*/ ['x'] = getInt();
+
   var /*@ type=num* */ v2 = t /*@target=Test::[]=*/ ['x'] = getNum();
-  var /*@ type=num* */ v4 = t /*@target=Test::[]=*/ ['x'] ??= getInt();
-  var /*@ type=num* */ v5 = t /*@target=Test::[]=*/ ['x'] ??= getNum();
-  var /*@ type=double* */ v7 = t /*@target=Test::[]=*/ ['x'] += getInt();
-  var /*@ type=double* */ v8 = t /*@target=Test::[]=*/ ['x'] += getNum();
-  var /*@ type=double* */ v10 = ++t /*@target=Test::[]=*/ ['x'];
-  var /*@ type=double* */ v11 = t /*@target=Test::[]=*/ ['x']++;
+
+  var /*@ type=num* */ v4 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getInt();
+
+  var /*@ type=num* */ v5 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getNum();
+
+  var /*@ type=double* */ v7 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+      'x'] /*@ target=double::+ */ += getInt();
+
+  var /*@ type=double* */ v8 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+      'x'] /*@ target=double::+ */ += getNum();
+
+  var /*@ type=double* */ v10 =
+      /*@ target=double::+ */ ++t
+          /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'];
+
+  var /*@ type=double* */ v11 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+      'x'] /*@ target=double::+ */ ++;
 }
 
 void test8(Test<double, num> t) {
   var /*@ type=int* */ v1 = t /*@target=Test::[]=*/ ['x'] = getInt();
+
   var /*@ type=num* */ v2 = t /*@target=Test::[]=*/ ['x'] = getNum();
+
   var /*@ type=double* */ v3 = t /*@target=Test::[]=*/ ['x'] = getDouble();
-  var /*@ type=num* */ v4 = t /*@target=Test::[]=*/ ['x'] ??= getInt();
-  var /*@ type=num* */ v5 = t /*@target=Test::[]=*/ ['x'] ??= getNum();
-  var /*@ type=double* */ v6 = t /*@target=Test::[]=*/ ['x'] ??= getDouble();
-  var /*@ type=double* */ v7 = t /*@target=Test::[]=*/ ['x'] += getInt();
-  var /*@ type=double* */ v8 = t /*@target=Test::[]=*/ ['x'] += getNum();
-  var /*@ type=double* */ v9 = t /*@target=Test::[]=*/ ['x'] += getDouble();
-  var /*@ type=double* */ v10 = ++t /*@target=Test::[]=*/ ['x'];
-  var /*@ type=double* */ v11 = t /*@target=Test::[]=*/ ['x']++;
+
+  var /*@ type=num* */ v4 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getInt();
+
+  var /*@ type=num* */ v5 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getNum();
+
+  var /*@ type=double* */ v6 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getDouble();
+
+  var /*@ type=double* */ v7 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+      'x'] /*@ target=double::+ */ += getInt();
+
+  var /*@ type=double* */ v8 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+      'x'] /*@ target=double::+ */ += getNum();
+
+  var /*@ type=double* */ v9 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+      'x'] /*@ target=double::+ */ += getDouble();
+
+  var /*@ type=double* */ v10 =
+      /*@ target=double::+ */ ++t
+          /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'];
+
+  var /*@ type=double* */ v11 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+      'x'] /*@ target=double::+ */ ++;
 }
 
 void test9(Test<double, double> t) {
   var /*@ type=num* */ v2 = t /*@target=Test::[]=*/ ['x'] = getNum();
+
   var /*@ type=double* */ v3 = t /*@target=Test::[]=*/ ['x'] = getDouble();
-  var /*@ type=num* */ v5 = t /*@target=Test::[]=*/ ['x'] ??= getNum();
-  var /*@ type=double* */ v6 = t /*@target=Test::[]=*/ ['x'] ??= getDouble();
-  var /*@ type=double* */ v7 = t /*@target=Test::[]=*/ ['x'] += getInt();
-  var /*@ type=double* */ v8 = t /*@target=Test::[]=*/ ['x'] += getNum();
-  var /*@ type=double* */ v9 = t /*@target=Test::[]=*/ ['x'] += getDouble();
-  var /*@ type=double* */ v10 = ++t /*@target=Test::[]=*/ ['x'];
-  var /*@ type=double* */ v11 = t /*@target=Test::[]=*/ ['x']++;
+
+  var /*@ type=num* */ v5 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getNum();
+
+  var /*@ type=double* */ v6 =
+      t /*@target=Test::[]*/ ['x'] /*@target=num::==*/ /*@target=Test::[]=*/ ??=
+          getDouble();
+
+  var /*@ type=double* */ v7 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+      'x'] /*@ target=double::+ */ += getInt();
+
+  var /*@ type=double* */ v8 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+      'x'] /*@ target=double::+ */ += getNum();
+
+  var /*@ type=double* */ v9 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+      'x'] /*@ target=double::+ */ += getDouble();
+
+  var /*@ type=double* */ v10 =
+      /*@ target=double::+ */ ++t
+          /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'];
+
+  var /*@ type=double* */ v11 = t /*@target=Test::[]*/ /*@target=Test::[]=*/ [
+      'x'] /*@ target=double::+ */ ++;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart.strong.expect
index 4b07b83..6e5b788 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart.strong.expect
@@ -2,40 +2,40 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:47:59: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
+// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:97:79: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
 // Try changing the type of the left hand side, or casting the right hand side to 'double'.
-//   var /*@ type=int* */ v7 = t /*@target=Test::[]=*/ ['x'] += getInt();
-//                                                           ^
+//       t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
+//                                                                               ^
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:50:30: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
+// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:109:28: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
 // Try changing the type of the left hand side, or casting the right hand side to 'double'.
-//   var /*@ type=int* */ v10 = ++t /*@target=Test::[]=*/ ['x'];
-//                              ^
+//       /*@ target=num::+ */ ++t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'];
+//                            ^
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:51:59: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
+// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:112:33: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
 // Try changing the type of the left hand side, or casting the right hand side to 'double'.
-//   var /*@ type=int* */ v11 = t /*@target=Test::[]=*/ ['x']++;
-//                                                           ^
-//
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:96:62: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
-// Try changing the type of the left hand side, or casting the right hand side to 'int'.
-//   var /*@ type=double* */ v7 = t /*@target=Test::[]=*/ ['x'] += getInt();
-//                                                              ^
-//
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:97:62: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
-// Try changing the type of the left hand side, or casting the right hand side to 'int'.
-//   var /*@ type=double* */ v8 = t /*@target=Test::[]=*/ ['x'] += getNum();
-//                                                              ^
-//
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:98:33: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
-// Try changing the type of the left hand side, or casting the right hand side to 'int'.
-//   var /*@ type=double* */ v10 = ++t /*@target=Test::[]=*/ ['x'];
+//       'x'] /*@ target=num::+ */ ++;
 //                                 ^
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:99:62: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:227:36: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
 // Try changing the type of the left hand side, or casting the right hand side to 'int'.
-//   var /*@ type=double* */ v11 = t /*@target=Test::[]=*/ ['x']++;
-//                                                              ^
+//       'x'] /*@ target=double::+ */ += getInt();
+//                                    ^
+//
+// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:230:36: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+//       'x'] /*@ target=double::+ */ += getNum();
+//                                    ^
+//
+// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:233:31: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+//       /*@ target=double::+ */ ++t
+//                               ^
+//
+// pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:237:36: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+// Try changing the type of the left hand side, or casting the right hand side to 'int'.
+//       'x'] /*@ target=double::+ */ ++;
+//                                    ^
 //
 import self as self;
 import "dart:core" as core;
@@ -81,20 +81,20 @@
   core::double* v3 = let final self::Test<core::int*, core::double*>* #t86 = t in let final core::String* #t87 = "x" in let final core::double* #t88 = self::getDouble() in let final void #t89 = #t86.{self::Test::[]=}(#t87, #t88) in #t88;
   core::num* v5 = let final self::Test<core::int*, core::double*>* #t90 = t in let final core::String* #t91 = "x" in let final core::int* #t92 = #t90.{self::Test::[]}(#t91) in #t92.{core::num::==}(null) ?{core::num*} let final core::num* #t93 = self::getNum() as{TypeError} core::double* in let final void #t94 = #t90.{self::Test::[]=}(#t91, #t93) in #t93 : #t92;
   core::num* v6 = let final self::Test<core::int*, core::double*>* #t95 = t in let final core::String* #t96 = "x" in let final core::int* #t97 = #t95.{self::Test::[]}(#t96) in #t97.{core::num::==}(null) ?{core::num*} let final core::double* #t98 = self::getDouble() in let final void #t99 = #t95.{self::Test::[]=}(#t96, #t98) in #t98 : #t97;
-  core::int* v7 = let final self::Test<core::int*, core::double*>* #t100 = t in let final core::String* #t101 = "x" in let final core::int* #t102 = let final<BottomType> #t103 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:47:59: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
+  core::int* v7 = let final self::Test<core::int*, core::double*>* #t100 = t in let final core::String* #t101 = "x" in let final core::int* #t102 = let final<BottomType> #t103 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:97:79: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
 Try changing the type of the left hand side, or casting the right hand side to 'double'.
-  var /*@ type=int* */ v7 = t /*@target=Test::[]=*/ ['x'] += getInt();
-                                                          ^" in #t100.{self::Test::[]}(#t101).{core::num::+}(self::getInt()) as{TypeError} core::double* in let final void #t104 = #t100.{self::Test::[]=}(#t101, #t102) in #t102;
+      t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'] /*@ target=num::+ */ +=
+                                                                              ^" in #t100.{self::Test::[]}(#t101).{core::num::+}(self::getInt()) as{TypeError} core::double* in let final void #t104 = #t100.{self::Test::[]=}(#t101, #t102) in #t102;
   core::num* v8 = let final self::Test<core::int*, core::double*>* #t105 = t in let final core::String* #t106 = "x" in let final core::num* #t107 = #t105.{self::Test::[]}(#t106).{core::num::+}(self::getNum()) as{TypeError} core::double* in let final void #t108 = #t105.{self::Test::[]=}(#t106, #t107) in #t107;
   core::double* v9 = let final self::Test<core::int*, core::double*>* #t109 = t in let final core::String* #t110 = "x" in let final core::double* #t111 = #t109.{self::Test::[]}(#t110).{core::num::+}(self::getDouble()) in let final void #t112 = #t109.{self::Test::[]=}(#t110, #t111) in #t111;
-  core::int* v10 = let final self::Test<core::int*, core::double*>* #t113 = t in let final core::String* #t114 = "x" in let final core::int* #t115 = let final<BottomType> #t116 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:50:30: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
+  core::int* v10 = let final self::Test<core::int*, core::double*>* #t113 = t in let final core::String* #t114 = "x" in let final core::int* #t115 = let final<BottomType> #t116 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:109:28: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
 Try changing the type of the left hand side, or casting the right hand side to 'double'.
-  var /*@ type=int* */ v10 = ++t /*@target=Test::[]=*/ ['x'];
-                             ^" in #t113.{self::Test::[]}(#t114).{core::num::+}(1) as{TypeError} core::double* in let final void #t117 = #t113.{self::Test::[]=}(#t114, #t115) in #t115;
-  core::int* v11 = let final self::Test<core::int*, core::double*>* #t118 = t in let final core::String* #t119 = "x" in let final core::int* #t120 = #t118.{self::Test::[]}(#t119) in let final void #t121 = #t118.{self::Test::[]=}(#t119, let final<BottomType> #t122 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:51:59: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
+      /*@ target=num::+ */ ++t /*@target=Test::[]*/ /*@target=Test::[]=*/ ['x'];
+                           ^" in #t113.{self::Test::[]}(#t114).{core::num::+}(1) as{TypeError} core::double* in let final void #t117 = #t113.{self::Test::[]=}(#t114, #t115) in #t115;
+  core::int* v11 = let final self::Test<core::int*, core::double*>* #t118 = t in let final core::String* #t119 = "x" in let final core::int* #t120 = #t118.{self::Test::[]}(#t119) in let final void #t121 = #t118.{self::Test::[]=}(#t119, let final<BottomType> #t122 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:112:33: Error: A value of type 'int' can't be assigned to a variable of type 'double'.
 Try changing the type of the left hand side, or casting the right hand side to 'double'.
-  var /*@ type=int* */ v11 = t /*@target=Test::[]=*/ ['x']++;
-                                                          ^" in #t120.{core::num::+}(1) as{TypeError} core::double*) in #t120;
+      'x'] /*@ target=num::+ */ ++;
+                                ^" in #t120.{core::num::+}(1) as{TypeError} core::double*) in #t120;
 }
 static method test4(self::Test<core::num*, core::int*>* t) → void {
   core::int* v1 = let final self::Test<core::num*, core::int*>* #t123 = t in let final core::String* #t124 = "x" in let final core::int* #t125 = self::getInt() in let final void #t126 = #t123.{self::Test::[]=}(#t124, #t125) in #t125;
@@ -135,22 +135,22 @@
   core::num* v2 = let final self::Test<core::double*, core::int*>* #t246 = t in let final core::String* #t247 = "x" in let final core::num* #t248 = self::getNum() as{TypeError} core::int* in let final void #t249 = #t246.{self::Test::[]=}(#t247, #t248) in #t248;
   core::num* v4 = let final self::Test<core::double*, core::int*>* #t250 = t in let final core::String* #t251 = "x" in let final core::double* #t252 = #t250.{self::Test::[]}(#t251) in #t252.{core::num::==}(null) ?{core::num*} let final core::int* #t253 = self::getInt() in let final void #t254 = #t250.{self::Test::[]=}(#t251, #t253) in #t253 : #t252;
   core::num* v5 = let final self::Test<core::double*, core::int*>* #t255 = t in let final core::String* #t256 = "x" in let final core::double* #t257 = #t255.{self::Test::[]}(#t256) in #t257.{core::num::==}(null) ?{core::num*} let final core::num* #t258 = self::getNum() as{TypeError} core::int* in let final void #t259 = #t255.{self::Test::[]=}(#t256, #t258) in #t258 : #t257;
-  core::double* v7 = let final self::Test<core::double*, core::int*>* #t260 = t in let final core::String* #t261 = "x" in let final core::double* #t262 = let final<BottomType> #t263 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:96:62: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+  core::double* v7 = let final self::Test<core::double*, core::int*>* #t260 = t in let final core::String* #t261 = "x" in let final core::double* #t262 = let final<BottomType> #t263 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:227:36: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
 Try changing the type of the left hand side, or casting the right hand side to 'int'.
-  var /*@ type=double* */ v7 = t /*@target=Test::[]=*/ ['x'] += getInt();
-                                                             ^" in #t260.{self::Test::[]}(#t261).{core::double::+}(self::getInt()) as{TypeError} core::int* in let final void #t264 = #t260.{self::Test::[]=}(#t261, #t262) in #t262;
-  core::double* v8 = let final self::Test<core::double*, core::int*>* #t265 = t in let final core::String* #t266 = "x" in let final core::double* #t267 = let final<BottomType> #t268 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:97:62: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+      'x'] /*@ target=double::+ */ += getInt();
+                                   ^" in #t260.{self::Test::[]}(#t261).{core::double::+}(self::getInt()) as{TypeError} core::int* in let final void #t264 = #t260.{self::Test::[]=}(#t261, #t262) in #t262;
+  core::double* v8 = let final self::Test<core::double*, core::int*>* #t265 = t in let final core::String* #t266 = "x" in let final core::double* #t267 = let final<BottomType> #t268 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:230:36: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
 Try changing the type of the left hand side, or casting the right hand side to 'int'.
-  var /*@ type=double* */ v8 = t /*@target=Test::[]=*/ ['x'] += getNum();
-                                                             ^" in #t265.{self::Test::[]}(#t266).{core::double::+}(self::getNum()) as{TypeError} core::int* in let final void #t269 = #t265.{self::Test::[]=}(#t266, #t267) in #t267;
-  core::double* v10 = let final self::Test<core::double*, core::int*>* #t270 = t in let final core::String* #t271 = "x" in let final core::double* #t272 = let final<BottomType> #t273 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:98:33: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+      'x'] /*@ target=double::+ */ += getNum();
+                                   ^" in #t265.{self::Test::[]}(#t266).{core::double::+}(self::getNum()) as{TypeError} core::int* in let final void #t269 = #t265.{self::Test::[]=}(#t266, #t267) in #t267;
+  core::double* v10 = let final self::Test<core::double*, core::int*>* #t270 = t in let final core::String* #t271 = "x" in let final core::double* #t272 = let final<BottomType> #t273 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:233:31: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
 Try changing the type of the left hand side, or casting the right hand side to 'int'.
-  var /*@ type=double* */ v10 = ++t /*@target=Test::[]=*/ ['x'];
-                                ^" in #t270.{self::Test::[]}(#t271).{core::double::+}(1) as{TypeError} core::int* in let final void #t274 = #t270.{self::Test::[]=}(#t271, #t272) in #t272;
-  core::double* v11 = let final self::Test<core::double*, core::int*>* #t275 = t in let final core::String* #t276 = "x" in let final core::double* #t277 = #t275.{self::Test::[]}(#t276) in let final void #t278 = #t275.{self::Test::[]=}(#t276, let final<BottomType> #t279 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:99:62: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+      /*@ target=double::+ */ ++t
+                              ^" in #t270.{self::Test::[]}(#t271).{core::double::+}(1) as{TypeError} core::int* in let final void #t274 = #t270.{self::Test::[]=}(#t271, #t272) in #t272;
+  core::double* v11 = let final self::Test<core::double*, core::int*>* #t275 = t in let final core::String* #t276 = "x" in let final core::double* #t277 = #t275.{self::Test::[]}(#t276) in let final void #t278 = #t275.{self::Test::[]=}(#t276, let final<BottomType> #t279 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_index_upwards.dart:237:36: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
 Try changing the type of the left hand side, or casting the right hand side to 'int'.
-  var /*@ type=double* */ v11 = t /*@target=Test::[]=*/ ['x']++;
-                                                             ^" in #t277.{core::double::+}(1) as{TypeError} core::int*) in #t277;
+      'x'] /*@ target=double::+ */ ++;
+                                   ^" in #t277.{core::double::+}(1) as{TypeError} core::int*) in #t277;
 }
 static method test8(self::Test<core::double*, core::num*>* t) → void {
   core::int* v1 = let final self::Test<core::double*, core::num*>* #t280 = t in let final core::String* #t281 = "x" in let final core::int* #t282 = self::getInt() in let final void #t283 = #t280.{self::Test::[]=}(#t281, #t282) in #t282;
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart
index ab2cac0..05354e5 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart
@@ -22,18 +22,22 @@
   B local;
   local = /*@ typeArgs=B* */ f();
   local ??= /*@ typeArgs=B* */ f();
-  local += /*@ typeArgs=dynamic */ f();
-  local *= /*@ typeArgs=dynamic */ f();
-  local &= /*@ typeArgs=dynamic */ f();
-  --local;
-  local--;
+  local /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+  local /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+  local /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+  /*@ target=B::- */ --local;
+  local /*@ target=B::- */ --;
   var /*@ type=B* */ v1 = local = /*@ typeArgs=B* */ f();
   var /*@ type=B* */ v2 = local ??= /*@ typeArgs=B* */ f();
-  var /*@ type=A* */ v3 = local += /*@ typeArgs=dynamic */ f();
-  var /*@ type=B* */ v4 = local *= /*@ typeArgs=dynamic */ f();
-  var /*@ type=C* */ v5 = local &= /*@ typeArgs=dynamic */ f();
-  var /*@ type=B* */ v6 = --local;
-  var /*@ type=B* */ v7 = local--;
+  var /*@ type=A* */ v3 = local
+      /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+  var /*@ type=B* */ v4 = local
+      /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+  var /*@ type=C* */ v5 = local
+      /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+  var /*@ type=B* */ v6 = /*@ target=B::- */ --local;
+  var /*@ type=B* */ v7 = /*@ type=B* */ local
+      /*@ type=B* */ /*@ target=B::- */ --;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.strong.expect
index 0330af0..35c6164 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.strong.expect
@@ -31,16 +31,16 @@
   self::B* local;
   local = self::f<self::B*>();
   local.{core::Object::==}(null) ?{self::B*} local = self::f<self::B*>() : null;
-  local = local.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-  local = local.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  local = local.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  local = local.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  local = local.{self::B::*}(self::f<self::B*>());
+  local = local.{self::B::&}(self::f<self::A*>());
   local = local.{self::B::-}(1);
   local = local.{self::B::-}(1);
   self::B* v1 = local = self::f<self::B*>();
   self::B* v2 = let final self::B* #t1 = local in #t1.{core::Object::==}(null) ?{self::B*} local = self::f<self::B*>() : #t1;
-  self::A* v3 = local = local.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-  self::B* v4 = local = local.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::C* v5 = local = local.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::A* v3 = local = local.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::B* v4 = local = local.{self::B::*}(self::f<self::B*>());
+  self::C* v5 = local = local.{self::B::&}(self::f<self::A*>());
   self::B* v6 = local = local.{self::B::-}(1);
   self::B* v7 = let final self::B* #t2 = local in let final self::B* #t3 = local = #t2.{self::B::-}(1) in #t2;
 }
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.strong.transformed.expect
index 0330af0..35c6164 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.strong.transformed.expect
@@ -31,16 +31,16 @@
   self::B* local;
   local = self::f<self::B*>();
   local.{core::Object::==}(null) ?{self::B*} local = self::f<self::B*>() : null;
-  local = local.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-  local = local.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  local = local.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  local = local.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  local = local.{self::B::*}(self::f<self::B*>());
+  local = local.{self::B::&}(self::f<self::A*>());
   local = local.{self::B::-}(1);
   local = local.{self::B::-}(1);
   self::B* v1 = local = self::f<self::B*>();
   self::B* v2 = let final self::B* #t1 = local in #t1.{core::Object::==}(null) ?{self::B*} local = self::f<self::B*>() : #t1;
-  self::A* v3 = local = local.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-  self::B* v4 = local = local.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::C* v5 = local = local.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::A* v3 = local = local.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::B* v4 = local = local.{self::B::*}(self::f<self::B*>());
+  self::C* v5 = local = local.{self::B::&}(self::f<self::A*>());
   self::B* v6 = local = local.{self::B::-}(1);
   self::B* v7 = let final self::B* #t2 = local in let final self::B* #t3 = local = #t2.{self::B::-}(1) in #t2;
 }
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.type_promotion.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.type_promotion.expect
index aa57cf4..7113cbf 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.type_promotion.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_local.dart.type_promotion.expect
@@ -4,39 +4,39 @@
 pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:24:9: Context: Write to local@474
   local ??= /*@ typeArgs=B* */ f();
         ^^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:25:9: Context: Write to local@474
-  local += /*@ typeArgs=dynamic */ f();
-        ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:26:9: Context: Write to local@474
-  local *= /*@ typeArgs=dynamic */ f();
-        ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:27:9: Context: Write to local@474
-  local &= /*@ typeArgs=dynamic */ f();
-        ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:28:3: Context: Write to local@474
-  --local;
-  ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:29:8: Context: Write to local@474
-  local--;
-       ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:25:28: Context: Write to local@474
+  local /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+                           ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:26:28: Context: Write to local@474
+  local /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+                           ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:27:28: Context: Write to local@474
+  local /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+                           ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:28:22: Context: Write to local@474
+  /*@ target=B::- */ --local;
+                     ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:29:28: Context: Write to local@474
+  local /*@ target=B::- */ --;
+                           ^^
 pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:30:33: Context: Write to local@474
   var /*@ type=B* */ v1 = local = /*@ typeArgs=B* */ f();
                                 ^
 pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:31:33: Context: Write to local@474
   var /*@ type=B* */ v2 = local ??= /*@ typeArgs=B* */ f();
                                 ^^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:32:33: Context: Write to local@474
-  var /*@ type=A* */ v3 = local += /*@ typeArgs=dynamic */ f();
-                                ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:33:33: Context: Write to local@474
-  var /*@ type=B* */ v4 = local *= /*@ typeArgs=dynamic */ f();
-                                ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:34:33: Context: Write to local@474
-  var /*@ type=C* */ v5 = local &= /*@ typeArgs=dynamic */ f();
-                                ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:35:27: Context: Write to local@474
-  var /*@ type=B* */ v6 = --local;
-                          ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:36:32: Context: Write to local@474
-  var /*@ type=B* */ v7 = local--;
-                               ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:33:26: Context: Write to local@474
+      /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+                         ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:35:26: Context: Write to local@474
+      /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+                         ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:37:26: Context: Write to local@474
+      /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+                         ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:38:46: Context: Write to local@474
+  var /*@ type=B* */ v6 = /*@ target=B::- */ --local;
+                                             ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local.dart:40:41: Context: Write to local@474
+      /*@ type=B* */ /*@ target=B::- */ --;
+                                        ^^
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart
index 62bba51..b88af64 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart
@@ -14,10 +14,11 @@
   var /*@ type=num* */ v2 = t = getNum();
   var /*@ type=int* */ v4 = t ??= getInt();
   var /*@ type=num* */ v5 = t ??= getNum();
-  var /*@ type=int* */ v7 = t += getInt();
-  var /*@ type=num* */ v8 = t += getNum();
-  var /*@ type=int* */ v10 = ++t;
-  var /*@ type=int* */ v11 = t++;
+  var /*@ type=int* */ v7 = t /*@ target=num::+ */ += getInt();
+  var /*@ type=num* */ v8 = t /*@ target=num::+ */ += getNum();
+  var /*@ type=int* */ v10 = /*@ target=num::+ */ ++t;
+  var /*@ type=int* */ v11 =
+      /*@ type=int* */ t /*@ type=int* */ /*@ target=num::+ */ ++;
 }
 
 void test2(num t) {
@@ -27,11 +28,12 @@
   var /*@ type=num* */ v4 = t ??= getInt();
   var /*@ type=num* */ v5 = t ??= getNum();
   var /*@ type=num* */ v6 = t ??= getDouble();
-  var /*@ type=num* */ v7 = t += getInt();
-  var /*@ type=num* */ v8 = t += getNum();
-  var /*@ type=num* */ v9 = t += getDouble();
-  var /*@ type=num* */ v10 = ++t;
-  var /*@ type=num* */ v11 = t++;
+  var /*@ type=num* */ v7 = t /*@ target=num::+ */ += getInt();
+  var /*@ type=num* */ v8 = t /*@ target=num::+ */ += getNum();
+  var /*@ type=num* */ v9 = t /*@ target=num::+ */ += getDouble();
+  var /*@ type=num* */ v10 = /*@ target=num::+ */ ++t;
+  var /*@ type=num* */ v11 =
+      /*@ type=num* */ t /*@ type=num* */ /*@ target=num::+ */ ++;
 }
 
 void test3(double t) {
@@ -39,11 +41,12 @@
   var /*@ type=double* */ v3 = t = getDouble();
   var /*@ type=num* */ v5 = t ??= getNum();
   var /*@ type=double* */ v6 = t ??= getDouble();
-  var /*@ type=double* */ v7 = t += getInt();
-  var /*@ type=double* */ v8 = t += getNum();
-  var /*@ type=double* */ v9 = t += getDouble();
-  var /*@ type=double* */ v10 = ++t;
-  var /*@ type=double* */ v11 = t++;
+  var /*@ type=double* */ v7 = t /*@ target=double::+ */ += getInt();
+  var /*@ type=double* */ v8 = t /*@ target=double::+ */ += getNum();
+  var /*@ type=double* */ v9 = t /*@ target=double::+ */ += getDouble();
+  var /*@ type=double* */ v10 = /*@ target=double::+ */ ++t;
+  var /*@ type=double* */ v11 =
+      /*@ type=double* */ t /*@ type=double* */ /*@ target=double::+ */ ++;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart.type_promotion.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart.type_promotion.expect
index 54a1aba..e076b03 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart.type_promotion.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart.type_promotion.expect
@@ -10,75 +10,75 @@
 pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:16:31: Context: Write to t@343
   var /*@ type=num* */ v5 = t ??= getNum();
                               ^^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:17:31: Context: Write to t@343
-  var /*@ type=int* */ v7 = t += getInt();
-                              ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:18:31: Context: Write to t@343
-  var /*@ type=num* */ v8 = t += getNum();
-                              ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:19:30: Context: Write to t@343
-  var /*@ type=int* */ v10 = ++t;
-                             ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:20:31: Context: Write to t@343
-  var /*@ type=int* */ v11 = t++;
-                              ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:24:31: Context: Write to t@343
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:17:52: Context: Write to t@343
+  var /*@ type=int* */ v7 = t /*@ target=num::+ */ += getInt();
+                                                   ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:18:52: Context: Write to t@343
+  var /*@ type=num* */ v8 = t /*@ target=num::+ */ += getNum();
+                                                   ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:19:51: Context: Write to t@343
+  var /*@ type=int* */ v10 = /*@ target=num::+ */ ++t;
+                                                  ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:21:64: Context: Write to t@343
+      /*@ type=int* */ t /*@ type=int* */ /*@ target=num::+ */ ++;
+                                                               ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:25:31: Context: Write to t@343
   var /*@ type=int* */ v1 = t = getInt();
                               ^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:25:31: Context: Write to t@343
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:26:31: Context: Write to t@343
   var /*@ type=num* */ v2 = t = getNum();
                               ^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:26:34: Context: Write to t@343
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:27:34: Context: Write to t@343
   var /*@ type=double* */ v3 = t = getDouble();
                                  ^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:27:31: Context: Write to t@343
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:28:31: Context: Write to t@343
   var /*@ type=num* */ v4 = t ??= getInt();
                               ^^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:28:31: Context: Write to t@343
-  var /*@ type=num* */ v5 = t ??= getNum();
-                              ^^^
 pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:29:31: Context: Write to t@343
-  var /*@ type=num* */ v6 = t ??= getDouble();
+  var /*@ type=num* */ v5 = t ??= getNum();
                               ^^^
 pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:30:31: Context: Write to t@343
-  var /*@ type=num* */ v7 = t += getInt();
-                              ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:31:31: Context: Write to t@343
-  var /*@ type=num* */ v8 = t += getNum();
-                              ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:32:31: Context: Write to t@343
-  var /*@ type=num* */ v9 = t += getDouble();
-                              ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:33:30: Context: Write to t@343
-  var /*@ type=num* */ v10 = ++t;
-                             ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:34:31: Context: Write to t@343
-  var /*@ type=num* */ v11 = t++;
-                              ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:38:31: Context: Write to t@343
+  var /*@ type=num* */ v6 = t ??= getDouble();
+                              ^^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:31:52: Context: Write to t@343
+  var /*@ type=num* */ v7 = t /*@ target=num::+ */ += getInt();
+                                                   ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:32:52: Context: Write to t@343
+  var /*@ type=num* */ v8 = t /*@ target=num::+ */ += getNum();
+                                                   ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:33:52: Context: Write to t@343
+  var /*@ type=num* */ v9 = t /*@ target=num::+ */ += getDouble();
+                                                   ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:34:51: Context: Write to t@343
+  var /*@ type=num* */ v10 = /*@ target=num::+ */ ++t;
+                                                  ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:36:64: Context: Write to t@343
+      /*@ type=num* */ t /*@ type=num* */ /*@ target=num::+ */ ++;
+                                                               ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:40:31: Context: Write to t@343
   var /*@ type=num* */ v2 = t = getNum();
                               ^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:39:34: Context: Write to t@343
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:41:34: Context: Write to t@343
   var /*@ type=double* */ v3 = t = getDouble();
                                  ^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:40:31: Context: Write to t@343
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:42:31: Context: Write to t@343
   var /*@ type=num* */ v5 = t ??= getNum();
                               ^^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:41:34: Context: Write to t@343
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:43:34: Context: Write to t@343
   var /*@ type=double* */ v6 = t ??= getDouble();
                                  ^^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:42:34: Context: Write to t@343
-  var /*@ type=double* */ v7 = t += getInt();
-                                 ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:43:34: Context: Write to t@343
-  var /*@ type=double* */ v8 = t += getNum();
-                                 ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:44:34: Context: Write to t@343
-  var /*@ type=double* */ v9 = t += getDouble();
-                                 ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:45:33: Context: Write to t@343
-  var /*@ type=double* */ v10 = ++t;
-                                ^^
-pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:46:34: Context: Write to t@343
-  var /*@ type=double* */ v11 = t++;
-                                 ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:44:58: Context: Write to t@343
+  var /*@ type=double* */ v7 = t /*@ target=double::+ */ += getInt();
+                                                         ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:45:58: Context: Write to t@343
+  var /*@ type=double* */ v8 = t /*@ target=double::+ */ += getNum();
+                                                         ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:46:58: Context: Write to t@343
+  var /*@ type=double* */ v9 = t /*@ target=double::+ */ += getDouble();
+                                                         ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:47:57: Context: Write to t@343
+  var /*@ type=double* */ v10 = /*@ target=double::+ */ ++t;
+                                                        ^^
+pkg/front_end/testcases/inference_new/infer_assign_to_local_upwards.dart:49:73: Context: Write to t@343
+      /*@ type=double* */ t /*@ type=double* */ /*@ target=double::+ */ ++;
+                                                                        ^^
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart
index 7b7d80f..18e21f8 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property.dart
@@ -10,12 +10,21 @@
 }
 
 var v_assign = (new A(). /*@target=A::f*/ f = 1);
-var v_plus = (new A(). /*@target=A::f*/ f += 1);
-var v_minus = (new A(). /*@target=A::f*/ f -= 1);
-var v_multiply = (new A(). /*@target=A::f*/ f *= 1);
-var v_prefix_pp = (++new A(). /*@target=A::f*/ f);
-var v_prefix_mm = (--new A(). /*@target=A::f*/ f);
-var v_postfix_pp = (new A(). /*@target=A::f*/ f++);
-var v_postfix_mm = (new A(). /*@target=A::f*/ f--);
+var v_plus = (new /*@ type=A* */ A()
+    . /*@target=A::f*/ /*@target=A::f*/ f /*@ target=num::+ */ += 1);
+var v_minus = (new /*@ type=A* */ A()
+    . /*@target=A::f*/ /*@target=A::f*/ f /*@ target=num::- */ -= 1);
+var v_multiply = (new /*@ type=A* */ A()
+    . /*@target=A::f*/ /*@target=A::f*/ f /*@ target=num::* */ *= 1);
+var v_prefix_pp = (/*@ target=num::+ */ ++new /*@ type=A* */ A()
+    . /*@target=A::f*/ /*@target=A::f*/ f);
+var v_prefix_mm = (/*@ target=num::- */ --new /*@ type=A* */ A()
+    . /*@target=A::f*/ /*@target=A::f*/ f);
+var v_postfix_pp = (new /*@ type=A* */ A()
+    . /*@ type=int* */ /*@target=A::f*/ /*@target=A::f*/
+    f /*@ type=int* */ /*@ target=num::+ */ ++);
+var v_postfix_mm = (new /*@ type=A* */ A()
+    . /*@ type=int* */ /*@target=A::f*/ /*@target=A::f*/
+    f /*@ type=int* */ /*@ target=num::- */ --);
 
 main() {}
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart
index 0a7493d..1878c4d 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart
@@ -14,9 +14,15 @@
   A a;
 }
 
-var v_prefix_pp = (++new B(). /*@target=B::a*/ a);
-var v_prefix_mm = (--new B(). /*@target=B::a*/ a);
-var v_postfix_pp = (new B(). /*@target=B::a*/ a++);
-var v_postfix_mm = (new B(). /*@target=B::a*/ a--);
+var v_prefix_pp = (/*@ target=A::+ */ ++new /*@ type=B* */ B()
+    . /*@target=B::a*/ /*@target=B::a*/ a);
+var v_prefix_mm = (/*@ target=A::- */ --new /*@ type=B* */ B()
+    . /*@target=B::a*/ /*@target=B::a*/ a);
+var v_postfix_pp =
+    (new /*@ type=B* */ B(). /*@ type=A* */ /*@target=B::a*/ /*@target=B::a*/ a
+        /*@ type=int* */ /*@ target=A::+ */ ++);
+var v_postfix_mm =
+    (new /*@ type=B* */ B(). /*@ type=A* */ /*@target=B::a*/ /*@target=B::a*/ a
+        /*@ type=double* */ /*@ target=A::- */ --);
 
 main() {}
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.strong.expect
index dd9255e..9749d80 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart.strong.expect
@@ -2,28 +2,28 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart:17:20: Error: A value of type 'int' can't be assigned to a variable of type 'A'.
+// pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart:17:39: Error: A value of type 'int' can't be assigned to a variable of type 'A'.
 //  - 'A' is from 'pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart'.
 // Try changing the type of the left hand side, or casting the right hand side to 'A'.
-// var v_prefix_pp = (++new B(). /*@target=B::a*/ a);
-//                    ^
+// var v_prefix_pp = (/*@ target=A::+ */ ++new /*@ type=B* */ B()
+//                                       ^
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart:18:20: Error: A value of type 'double' can't be assigned to a variable of type 'A'.
+// pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart:19:39: Error: A value of type 'double' can't be assigned to a variable of type 'A'.
 //  - 'A' is from 'pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart'.
 // Try changing the type of the left hand side, or casting the right hand side to 'A'.
-// var v_prefix_mm = (--new B(). /*@target=B::a*/ a);
-//                    ^
+// var v_prefix_mm = (/*@ target=A::- */ --new /*@ type=B* */ B()
+//                                       ^
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart:19:48: Error: A value of type 'int' can't be assigned to a variable of type 'A'.
+// pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart:23:45: Error: A value of type 'int' can't be assigned to a variable of type 'A'.
 //  - 'A' is from 'pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart'.
 // Try changing the type of the left hand side, or casting the right hand side to 'A'.
-// var v_postfix_pp = (new B(). /*@target=B::a*/ a++);
-//                                                ^
+//         /*@ type=int* */ /*@ target=A::+ */ ++);
+//                                             ^
 //
-// pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart:20:48: Error: A value of type 'double' can't be assigned to a variable of type 'A'.
+// pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart:26:48: Error: A value of type 'double' can't be assigned to a variable of type 'A'.
 //  - 'A' is from 'pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart'.
 // Try changing the type of the left hand side, or casting the right hand side to 'A'.
-// var v_postfix_mm = (new B(). /*@target=B::a*/ a--);
+//         /*@ type=double* */ /*@ target=A::- */ --);
 //                                                ^
 //
 import self as self;
@@ -44,24 +44,24 @@
     : super core::Object::•()
     ;
 }
-static field core::int* v_prefix_pp = let final self::B* #t1 = new self::B::•() in #t1.{self::B::a} = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart:17:20: Error: A value of type 'int' can't be assigned to a variable of type 'A'.
+static field core::int* v_prefix_pp = let final self::B* #t1 = new self::B::•() in #t1.{self::B::a} = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart:17:39: Error: A value of type 'int' can't be assigned to a variable of type 'A'.
  - 'A' is from 'pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart'.
 Try changing the type of the left hand side, or casting the right hand side to 'A'.
-var v_prefix_pp = (++new B(). /*@target=B::a*/ a);
-                   ^" in #t1.{self::B::a}.{self::A::+}(1) as{TypeError} self::A*;
-static field core::double* v_prefix_mm = let final self::B* #t3 = new self::B::•() in #t3.{self::B::a} = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart:18:20: Error: A value of type 'double' can't be assigned to a variable of type 'A'.
+var v_prefix_pp = (/*@ target=A::+ */ ++new /*@ type=B* */ B()
+                                      ^" in #t1.{self::B::a}.{self::A::+}(1) as{TypeError} self::A*;
+static field core::double* v_prefix_mm = let final self::B* #t3 = new self::B::•() in #t3.{self::B::a} = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart:19:39: Error: A value of type 'double' can't be assigned to a variable of type 'A'.
  - 'A' is from 'pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart'.
 Try changing the type of the left hand side, or casting the right hand side to 'A'.
-var v_prefix_mm = (--new B(). /*@target=B::a*/ a);
-                   ^" in #t3.{self::B::a}.{self::A::-}(1) as{TypeError} self::A*;
-static field self::A* v_postfix_pp = let final self::B* #t5 = new self::B::•() in let final self::A* #t6 = #t5.{self::B::a} in let final core::int* #t7 = #t5.{self::B::a} = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart:19:48: Error: A value of type 'int' can't be assigned to a variable of type 'A'.
+var v_prefix_mm = (/*@ target=A::- */ --new /*@ type=B* */ B()
+                                      ^" in #t3.{self::B::a}.{self::A::-}(1) as{TypeError} self::A*;
+static field self::A* v_postfix_pp = let final self::B* #t5 = new self::B::•() in let final self::A* #t6 = #t5.{self::B::a} in let final core::int* #t7 = #t5.{self::B::a} = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart:23:45: Error: A value of type 'int' can't be assigned to a variable of type 'A'.
  - 'A' is from 'pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart'.
 Try changing the type of the left hand side, or casting the right hand side to 'A'.
-var v_postfix_pp = (new B(). /*@target=B::a*/ a++);
-                                               ^" in #t6.{self::A::+}(1) as{TypeError} self::A* in #t6;
-static field self::A* v_postfix_mm = let final self::B* #t9 = new self::B::•() in let final self::A* #t10 = #t9.{self::B::a} in let final core::double* #t11 = #t9.{self::B::a} = let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart:20:48: Error: A value of type 'double' can't be assigned to a variable of type 'A'.
+        /*@ type=int* */ /*@ target=A::+ */ ++);
+                                            ^" in #t6.{self::A::+}(1) as{TypeError} self::A* in #t6;
+static field self::A* v_postfix_mm = let final self::B* #t9 = new self::B::•() in let final self::A* #t10 = #t9.{self::B::a} in let final core::double* #t11 = #t9.{self::B::a} = let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart:26:48: Error: A value of type 'double' can't be assigned to a variable of type 'A'.
  - 'A' is from 'pkg/front_end/testcases/inference_new/infer_assign_to_property_custom.dart'.
 Try changing the type of the left hand side, or casting the right hand side to 'A'.
-var v_postfix_mm = (new B(). /*@target=B::a*/ a--);
+        /*@ type=double* */ /*@ target=A::- */ --);
                                                ^" in #t10.{self::A::-}(1) as{TypeError} self::A* in #t10;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart
index 6a0d229..0fc74d0 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart
@@ -23,24 +23,46 @@
 
   static void test(Test t) {
     t. /*@target=Test::member*/ member = /*@ typeArgs=B* */ f();
-    t. /*@target=Test::member*/ member ??= /*@ typeArgs=B* */ f();
-    t. /*@target=Test::member*/ member += /*@ typeArgs=dynamic */ f();
-    t. /*@target=Test::member*/ member *= /*@ typeArgs=dynamic */ f();
-    t. /*@target=Test::member*/ member &= /*@ typeArgs=dynamic */ f();
-    --t. /*@target=Test::member*/ member;
-    t. /*@target=Test::member*/ member--;
+    /*@ type=Test* */ t
+            . /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@target=Object::==*/ ??= /*@ typeArgs=B* */ f();
+    /*@ type=Test* */ t
+            . /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+    /*@ type=Test* */ t
+            . /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+    /*@ type=Test* */ t
+            . /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+    /*@ target=B::- */ -- /*@ type=Test* */ t
+        . /*@target=Test::member*/ /*@target=Test::member*/ member;
+    /*@ type=Test* */ t
+            . /*@target=Test::member*/ /*@target=Test::member*/ member
+        /*@ target=B::- */ --;
     var /*@ type=B* */ v1 =
         t. /*@target=Test::member*/ member = /*@ typeArgs=B* */ f();
     var /*@ type=B* */ v2 =
-        t. /*@target=Test::member*/ member ??= /*@ typeArgs=B* */ f();
+        /*@ type=Test* */ t
+                . /*@target=Test::member*/ /*@target=Test::member*/ member
+            /*@target=Object::==*/ ??= /*@ typeArgs=B* */ f();
     var /*@ type=A* */ v3 =
-        t. /*@target=Test::member*/ member += /*@ typeArgs=dynamic */ f();
+        /*@ type=Test* */ t
+                . /*@target=Test::member*/ /*@target=Test::member*/ member
+            /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
     var /*@ type=B* */ v4 =
-        t. /*@target=Test::member*/ member *= /*@ typeArgs=dynamic */ f();
+        /*@ type=Test* */ t
+                . /*@target=Test::member*/ /*@target=Test::member*/ member
+            /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
     var /*@ type=C* */ v5 =
-        t. /*@target=Test::member*/ member &= /*@ typeArgs=dynamic */ f();
-    var /*@ type=B* */ v6 = --t. /*@target=Test::member*/ member;
-    var /*@ type=B* */ v7 = t. /*@target=Test::member*/ member--;
+        /*@ type=Test* */ t
+                . /*@target=Test::member*/ /*@target=Test::member*/ member
+            /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+    var /*@ type=B* */ v6 = /*@ target=B::- */ -- /*@ type=Test* */ t
+        . /*@target=Test::member*/ /*@target=Test::member*/ member;
+    var /*@ type=B* */ v7 = /*@ type=Test* */ t
+        . /*@ type=B* */ /*@target=Test::member*/ /*@target=Test::member*/
+        member /*@ type=B* */ /*@ target=B::- */ --;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart.strong.expect
index 74778b8..5809936 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart.strong.expect
@@ -33,16 +33,16 @@
   static method test(self::Test* t) → void {
     t.{self::Test::member} = self::f<self::B*>();
     let final self::Test* #t1 = t in #t1.{self::Test::member}.{core::Object::==}(null) ?{self::B*} #t1.{self::Test::member} = self::f<self::B*>() : null;
-    let final self::Test* #t2 = t in #t2.{self::Test::member} = #t2.{self::Test::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-    let final self::Test* #t3 = t in #t3.{self::Test::member} = #t3.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    let final self::Test* #t4 = t in #t4.{self::Test::member} = #t4.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    let final self::Test* #t2 = t in #t2.{self::Test::member} = #t2.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    let final self::Test* #t3 = t in #t3.{self::Test::member} = #t3.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    let final self::Test* #t4 = t in #t4.{self::Test::member} = #t4.{self::Test::member}.{self::B::&}(self::f<self::A*>());
     let final self::Test* #t5 = t in #t5.{self::Test::member} = #t5.{self::Test::member}.{self::B::-}(1);
     let final self::Test* #t6 = t in #t6.{self::Test::member} = #t6.{self::Test::member}.{self::B::-}(1);
     self::B* v1 = t.{self::Test::member} = self::f<self::B*>();
     self::B* v2 = let final self::Test* #t7 = t in let final self::B* #t8 = #t7.{self::Test::member} in #t8.{core::Object::==}(null) ?{self::B*} #t7.{self::Test::member} = self::f<self::B*>() : #t8;
-    self::A* v3 = let final self::Test* #t9 = t in #t9.{self::Test::member} = #t9.{self::Test::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-    self::B* v4 = let final self::Test* #t10 = t in #t10.{self::Test::member} = #t10.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    self::C* v5 = let final self::Test* #t11 = t in #t11.{self::Test::member} = #t11.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    self::A* v3 = let final self::Test* #t9 = t in #t9.{self::Test::member} = #t9.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    self::B* v4 = let final self::Test* #t10 = t in #t10.{self::Test::member} = #t10.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    self::C* v5 = let final self::Test* #t11 = t in #t11.{self::Test::member} = #t11.{self::Test::member}.{self::B::&}(self::f<self::A*>());
     self::B* v6 = let final self::Test* #t12 = t in #t12.{self::Test::member} = #t12.{self::Test::member}.{self::B::-}(1);
     self::B* v7 = let final self::Test* #t13 = t in let final self::B* #t14 = #t13.{self::Test::member} in let final self::B* #t15 = #t13.{self::Test::member} = #t14.{self::B::-}(1) in #t14;
   }
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart.strong.transformed.expect
index 74778b8..5809936 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart.strong.transformed.expect
@@ -33,16 +33,16 @@
   static method test(self::Test* t) → void {
     t.{self::Test::member} = self::f<self::B*>();
     let final self::Test* #t1 = t in #t1.{self::Test::member}.{core::Object::==}(null) ?{self::B*} #t1.{self::Test::member} = self::f<self::B*>() : null;
-    let final self::Test* #t2 = t in #t2.{self::Test::member} = #t2.{self::Test::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-    let final self::Test* #t3 = t in #t3.{self::Test::member} = #t3.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    let final self::Test* #t4 = t in #t4.{self::Test::member} = #t4.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    let final self::Test* #t2 = t in #t2.{self::Test::member} = #t2.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    let final self::Test* #t3 = t in #t3.{self::Test::member} = #t3.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    let final self::Test* #t4 = t in #t4.{self::Test::member} = #t4.{self::Test::member}.{self::B::&}(self::f<self::A*>());
     let final self::Test* #t5 = t in #t5.{self::Test::member} = #t5.{self::Test::member}.{self::B::-}(1);
     let final self::Test* #t6 = t in #t6.{self::Test::member} = #t6.{self::Test::member}.{self::B::-}(1);
     self::B* v1 = t.{self::Test::member} = self::f<self::B*>();
     self::B* v2 = let final self::Test* #t7 = t in let final self::B* #t8 = #t7.{self::Test::member} in #t8.{core::Object::==}(null) ?{self::B*} #t7.{self::Test::member} = self::f<self::B*>() : #t8;
-    self::A* v3 = let final self::Test* #t9 = t in #t9.{self::Test::member} = #t9.{self::Test::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-    self::B* v4 = let final self::Test* #t10 = t in #t10.{self::Test::member} = #t10.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    self::C* v5 = let final self::Test* #t11 = t in #t11.{self::Test::member} = #t11.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    self::A* v3 = let final self::Test* #t9 = t in #t9.{self::Test::member} = #t9.{self::Test::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    self::B* v4 = let final self::Test* #t10 = t in #t10.{self::Test::member} = #t10.{self::Test::member}.{self::B::*}(self::f<self::B*>());
+    self::C* v5 = let final self::Test* #t11 = t in #t11.{self::Test::member} = #t11.{self::Test::member}.{self::B::&}(self::f<self::A*>());
     self::B* v6 = let final self::Test* #t12 = t in #t12.{self::Test::member} = #t12.{self::Test::member}.{self::B::-}(1);
     self::B* v7 = let final self::Test* #t13 = t in let final self::B* #t14 = #t13.{self::Test::member} in let final self::B* #t15 = #t13.{self::Test::member} = #t14.{self::B::-}(1) in #t14;
   }
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart
index 45300f9..b2b1f77 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart
@@ -22,7 +22,8 @@
   B member;
 
   static void test(Test t) {
-    t?. /*@target=Test::member*/ member = /*@ typeArgs=B* */ f();
+    /*@ type=Test* */ /*@target=Object::==*/ t
+        ?. /*@target=Test::member*/ member = /*@ typeArgs=B* */ f();
     t?. /*@target=Test::member*/ member ??= /*@ typeArgs=B* */ f();
     t?. /*@target=Test::member*/ member += /*@ typeArgs=dynamic */ f();
     t?. /*@target=Test::member*/ member *= /*@ typeArgs=dynamic */ f();
@@ -30,7 +31,8 @@
     --t?. /*@target=Test::member*/ member;
     t?. /*@target=Test::member*/ member--;
     var /*@ type=B* */ v1 =
-        t?. /*@target=Test::member*/ member = /*@ typeArgs=B* */ f();
+        /*@ type=Test* */ /*@target=Object::==*/ t
+            ?. /*@target=Test::member*/ member = /*@ typeArgs=B* */ f();
     var /*@ type=B* */ v2 =
         t?. /*@target=Test::member*/ member ??= /*@ typeArgs=B* */ f();
     var /*@ type=A* */ v3 =
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart.strong.expect
index fdee8a4..52f7978 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart.strong.expect
@@ -31,14 +31,14 @@
     : super core::Object::•()
     ;
   static method test(self::Test* t) → void {
-    let final self::Test* #t1 = t in #t1.==(null) ?{self::B*} null : #t1.{self::Test::member} = self::f<self::B*>();
+    let final self::Test* #t1 = t in #t1.{core::Object::==}(null) ?{self::B*} null : #t1.{self::Test::member} = self::f<self::B*>();
     let final self::Test* #t2 = t in #t2.==(null) ?{self::B*} null : #t2.{self::Test::member}.{core::Object::==}(null) ?{self::B*} #t2.{self::Test::member} = self::f<self::B*>() : null;
     let final self::Test* #t3 = t in #t3.==(null) ?{self::A*} null : #t3.{self::Test::member} = #t3.{self::Test::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
     let final self::Test* #t4 = t in #t4.==(null) ?{self::B*} null : #t4.{self::Test::member} = #t4.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
     let final self::Test* #t5 = t in #t5.==(null) ?{self::C*} null : #t5.{self::Test::member} = #t5.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
     let final self::Test* #t6 = t in #t6.==(null) ?{self::B*} null : #t6.{self::Test::member} = #t6.{self::Test::member}.{self::B::-}(1);
     let final self::Test* #t7 = t in #t7.==(null) ?{self::B*} null : #t7.{self::Test::member} = #t7.{self::Test::member}.{self::B::-}(1);
-    self::B* v1 = let final self::Test* #t8 = t in #t8.==(null) ?{self::B*} null : #t8.{self::Test::member} = self::f<self::B*>();
+    self::B* v1 = let final self::Test* #t8 = t in #t8.{core::Object::==}(null) ?{self::B*} null : #t8.{self::Test::member} = self::f<self::B*>();
     self::B* v2 = let final self::Test* #t9 = t in #t9.==(null) ?{self::B*} null : let final self::B* #t10 = #t9.{self::Test::member} in #t10.{core::Object::==}(null) ?{self::B*} #t9.{self::Test::member} = self::f<self::B*>() : #t10;
     self::A* v3 = let final self::Test* #t11 = t in #t11.==(null) ?{self::A*} null : #t11.{self::Test::member} = #t11.{self::Test::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
     self::B* v4 = let final self::Test* #t12 = t in #t12.==(null) ?{self::B*} null : #t12.{self::Test::member} = #t12.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart.strong.transformed.expect
index fdee8a4..52f7978 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware.dart.strong.transformed.expect
@@ -31,14 +31,14 @@
     : super core::Object::•()
     ;
   static method test(self::Test* t) → void {
-    let final self::Test* #t1 = t in #t1.==(null) ?{self::B*} null : #t1.{self::Test::member} = self::f<self::B*>();
+    let final self::Test* #t1 = t in #t1.{core::Object::==}(null) ?{self::B*} null : #t1.{self::Test::member} = self::f<self::B*>();
     let final self::Test* #t2 = t in #t2.==(null) ?{self::B*} null : #t2.{self::Test::member}.{core::Object::==}(null) ?{self::B*} #t2.{self::Test::member} = self::f<self::B*>() : null;
     let final self::Test* #t3 = t in #t3.==(null) ?{self::A*} null : #t3.{self::Test::member} = #t3.{self::Test::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
     let final self::Test* #t4 = t in #t4.==(null) ?{self::B*} null : #t4.{self::Test::member} = #t4.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
     let final self::Test* #t5 = t in #t5.==(null) ?{self::C*} null : #t5.{self::Test::member} = #t5.{self::Test::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
     let final self::Test* #t6 = t in #t6.==(null) ?{self::B*} null : #t6.{self::Test::member} = #t6.{self::Test::member}.{self::B::-}(1);
     let final self::Test* #t7 = t in #t7.==(null) ?{self::B*} null : #t7.{self::Test::member} = #t7.{self::Test::member}.{self::B::-}(1);
-    self::B* v1 = let final self::Test* #t8 = t in #t8.==(null) ?{self::B*} null : #t8.{self::Test::member} = self::f<self::B*>();
+    self::B* v1 = let final self::Test* #t8 = t in #t8.{core::Object::==}(null) ?{self::B*} null : #t8.{self::Test::member} = self::f<self::B*>();
     self::B* v2 = let final self::Test* #t9 = t in #t9.==(null) ?{self::B*} null : let final self::B* #t10 = #t9.{self::Test::member} in #t10.{core::Object::==}(null) ?{self::B*} #t9.{self::Test::member} = self::f<self::B*>() : #t10;
     self::A* v3 = let final self::Test* #t11 = t in #t11.==(null) ?{self::A*} null : #t11.{self::Test::member} = #t11.{self::Test::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
     self::B* v4 = let final self::Test* #t12 = t in #t12.==(null) ?{self::B*} null : #t12.{self::Test::member} = #t12.{self::Test::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart
index 664ca78..a8d4387 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart
@@ -13,8 +13,10 @@
   int prop;
 
   static void test(Test1 t) {
-    var /*@ type=int* */ v1 = t?. /*@target=Test1::prop*/ prop = getInt();
-    var /*@ type=num* */ v2 = t?. /*@target=Test1::prop*/ prop = getNum();
+    var /*@ type=int* */ v1 = /*@ type=Test1* */ /*@target=Object::==*/ t
+        ?. /*@target=Test1::prop*/ prop = getInt();
+    var /*@ type=num* */ v2 = /*@ type=Test1* */ /*@target=Object::==*/ t
+        ?. /*@target=Test1::prop*/ prop = getNum();
     var /*@ type=int* */ v4 = t?. /*@target=Test1::prop*/ prop ??= getInt();
     var /*@ type=num* */ v5 = t?. /*@target=Test1::prop*/ prop ??= getNum();
     var /*@ type=int* */ v7 = t?. /*@target=Test1::prop*/ prop += getInt();
@@ -28,9 +30,12 @@
   num prop;
 
   static void test(Test2 t) {
-    var /*@ type=int* */ v1 = t?. /*@target=Test2::prop*/ prop = getInt();
-    var /*@ type=num* */ v2 = t?. /*@target=Test2::prop*/ prop = getNum();
-    var /*@ type=double* */ v3 = t?. /*@target=Test2::prop*/ prop = getDouble();
+    var /*@ type=int* */ v1 = /*@ type=Test2* */ /*@target=Object::==*/ t
+        ?. /*@target=Test2::prop*/ prop = getInt();
+    var /*@ type=num* */ v2 = /*@ type=Test2* */ /*@target=Object::==*/ t
+        ?. /*@target=Test2::prop*/ prop = getNum();
+    var /*@ type=double* */ v3 = /*@ type=Test2* */ /*@target=Object::==*/ t
+        ?. /*@target=Test2::prop*/ prop = getDouble();
     var /*@ type=num* */ v4 = t?. /*@target=Test2::prop*/ prop ??= getInt();
     var /*@ type=num* */ v5 = t?. /*@target=Test2::prop*/ prop ??= getNum();
     var /*@ type=num* */ v6 = t?. /*@target=Test2::prop*/ prop ??= getDouble();
@@ -46,13 +51,17 @@
   double prop;
 
   static void test3(Test3 t) {
-    var /*@ type=num* */ v2 = t?. /*@target=Test3::prop*/ prop = getNum();
-    var /*@ type=double* */ v3 = t?. /*@target=Test3::prop*/ prop = getDouble();
+    var /*@ type=num* */ v2 = /*@ type=Test3* */ /*@target=Object::==*/ t
+        ?. /*@target=Test3::prop*/ prop = getNum();
+    var /*@ type=double* */ v3 = /*@ type=Test3* */ /*@target=Object::==*/ t
+        ?. /*@target=Test3::prop*/ prop = getDouble();
     var /*@ type=num* */ v5 = t?. /*@target=Test3::prop*/ prop ??= getNum();
-    var /*@ type=double* */ v6 = t?. /*@target=Test3::prop*/ prop ??= getDouble();
+    var /*@ type=double* */ v6 =
+        t?. /*@target=Test3::prop*/ prop ??= getDouble();
     var /*@ type=double* */ v7 = t?. /*@target=Test3::prop*/ prop += getInt();
     var /*@ type=double* */ v8 = t?. /*@target=Test3::prop*/ prop += getNum();
-    var /*@ type=double* */ v9 = t?. /*@target=Test3::prop*/ prop += getDouble();
+    var /*@ type=double* */ v9 =
+        t?. /*@target=Test3::prop*/ prop += getDouble();
     var /*@ type=double* */ v10 = ++t?. /*@target=Test3::prop*/ prop;
     var /*@ type=double* */ v11 = t?. /*@target=Test3::prop*/ prop++;
   }
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart.strong.expect
index 35c7161..da54b4b 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart.strong.expect
@@ -8,8 +8,8 @@
     : super core::Object::•()
     ;
   static method test(self::Test1* t) → void {
-    core::int* v1 = let final self::Test1* #t1 = t in #t1.==(null) ?{core::int*} null : #t1.{self::Test1::prop} = self::getInt();
-    core::num* v2 = let final self::Test1* #t2 = t in #t2.==(null) ?{core::num*} null : #t2.{self::Test1::prop} = self::getNum() as{TypeError} core::int*;
+    core::int* v1 = let final self::Test1* #t1 = t in #t1.{core::Object::==}(null) ?{core::int*} null : #t1.{self::Test1::prop} = self::getInt();
+    core::num* v2 = let final self::Test1* #t2 = t in #t2.{core::Object::==}(null) ?{core::num*} null : #t2.{self::Test1::prop} = self::getNum() as{TypeError} core::int*;
     core::int* v4 = let final self::Test1* #t3 = t in #t3.==(null) ?{core::int*} null : let final core::int* #t4 = #t3.{self::Test1::prop} in #t4.{core::num::==}(null) ?{core::int*} #t3.{self::Test1::prop} = self::getInt() : #t4;
     core::num* v5 = let final self::Test1* #t5 = t in #t5.==(null) ?{core::num*} null : let final core::int* #t6 = #t5.{self::Test1::prop} in #t6.{core::num::==}(null) ?{core::num*} #t5.{self::Test1::prop} = self::getNum() as{TypeError} core::int* : #t6;
     core::int* v7 = let final self::Test1* #t7 = t in #t7.==(null) ?{core::int*} null : #t7.{self::Test1::prop} = #t7.{self::Test1::prop}.{core::num::+}(self::getInt());
@@ -24,9 +24,9 @@
     : super core::Object::•()
     ;
   static method test(self::Test2* t) → void {
-    core::int* v1 = let final self::Test2* #t13 = t in #t13.==(null) ?{core::int*} null : #t13.{self::Test2::prop} = self::getInt();
-    core::num* v2 = let final self::Test2* #t14 = t in #t14.==(null) ?{core::num*} null : #t14.{self::Test2::prop} = self::getNum();
-    core::double* v3 = let final self::Test2* #t15 = t in #t15.==(null) ?{core::double*} null : #t15.{self::Test2::prop} = self::getDouble();
+    core::int* v1 = let final self::Test2* #t13 = t in #t13.{core::Object::==}(null) ?{core::int*} null : #t13.{self::Test2::prop} = self::getInt();
+    core::num* v2 = let final self::Test2* #t14 = t in #t14.{core::Object::==}(null) ?{core::num*} null : #t14.{self::Test2::prop} = self::getNum();
+    core::double* v3 = let final self::Test2* #t15 = t in #t15.{core::Object::==}(null) ?{core::double*} null : #t15.{self::Test2::prop} = self::getDouble();
     core::num* v4 = let final self::Test2* #t16 = t in #t16.==(null) ?{core::num*} null : let final core::num* #t17 = #t16.{self::Test2::prop} in #t17.{core::num::==}(null) ?{core::num*} #t16.{self::Test2::prop} = self::getInt() : #t17;
     core::num* v5 = let final self::Test2* #t18 = t in #t18.==(null) ?{core::num*} null : let final core::num* #t19 = #t18.{self::Test2::prop} in #t19.{core::num::==}(null) ?{core::num*} #t18.{self::Test2::prop} = self::getNum() : #t19;
     core::num* v6 = let final self::Test2* #t20 = t in #t20.==(null) ?{core::num*} null : let final core::num* #t21 = #t20.{self::Test2::prop} in #t21.{core::num::==}(null) ?{core::num*} #t20.{self::Test2::prop} = self::getDouble() : #t21;
@@ -43,8 +43,8 @@
     : super core::Object::•()
     ;
   static method test3(self::Test3* t) → void {
-    core::num* v2 = let final self::Test3* #t29 = t in #t29.==(null) ?{core::num*} null : #t29.{self::Test3::prop} = self::getNum() as{TypeError} core::double*;
-    core::double* v3 = let final self::Test3* #t30 = t in #t30.==(null) ?{core::double*} null : #t30.{self::Test3::prop} = self::getDouble();
+    core::num* v2 = let final self::Test3* #t29 = t in #t29.{core::Object::==}(null) ?{core::num*} null : #t29.{self::Test3::prop} = self::getNum() as{TypeError} core::double*;
+    core::double* v3 = let final self::Test3* #t30 = t in #t30.{core::Object::==}(null) ?{core::double*} null : #t30.{self::Test3::prop} = self::getDouble();
     core::num* v5 = let final self::Test3* #t31 = t in #t31.==(null) ?{core::num*} null : let final core::double* #t32 = #t31.{self::Test3::prop} in #t32.{core::num::==}(null) ?{core::num*} #t31.{self::Test3::prop} = self::getNum() as{TypeError} core::double* : #t32;
     core::double* v6 = let final self::Test3* #t33 = t in #t33.==(null) ?{core::double*} null : let final core::double* #t34 = #t33.{self::Test3::prop} in #t34.{core::num::==}(null) ?{core::double*} #t33.{self::Test3::prop} = self::getDouble() : #t34;
     core::double* v7 = let final self::Test3* #t35 = t in #t35.==(null) ?{core::double*} null : #t35.{self::Test3::prop} = #t35.{self::Test3::prop}.{core::double::+}(self::getInt());
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart.strong.transformed.expect
index 35c7161..da54b4b 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_null_aware_upwards.dart.strong.transformed.expect
@@ -8,8 +8,8 @@
     : super core::Object::•()
     ;
   static method test(self::Test1* t) → void {
-    core::int* v1 = let final self::Test1* #t1 = t in #t1.==(null) ?{core::int*} null : #t1.{self::Test1::prop} = self::getInt();
-    core::num* v2 = let final self::Test1* #t2 = t in #t2.==(null) ?{core::num*} null : #t2.{self::Test1::prop} = self::getNum() as{TypeError} core::int*;
+    core::int* v1 = let final self::Test1* #t1 = t in #t1.{core::Object::==}(null) ?{core::int*} null : #t1.{self::Test1::prop} = self::getInt();
+    core::num* v2 = let final self::Test1* #t2 = t in #t2.{core::Object::==}(null) ?{core::num*} null : #t2.{self::Test1::prop} = self::getNum() as{TypeError} core::int*;
     core::int* v4 = let final self::Test1* #t3 = t in #t3.==(null) ?{core::int*} null : let final core::int* #t4 = #t3.{self::Test1::prop} in #t4.{core::num::==}(null) ?{core::int*} #t3.{self::Test1::prop} = self::getInt() : #t4;
     core::num* v5 = let final self::Test1* #t5 = t in #t5.==(null) ?{core::num*} null : let final core::int* #t6 = #t5.{self::Test1::prop} in #t6.{core::num::==}(null) ?{core::num*} #t5.{self::Test1::prop} = self::getNum() as{TypeError} core::int* : #t6;
     core::int* v7 = let final self::Test1* #t7 = t in #t7.==(null) ?{core::int*} null : #t7.{self::Test1::prop} = #t7.{self::Test1::prop}.{core::num::+}(self::getInt());
@@ -24,9 +24,9 @@
     : super core::Object::•()
     ;
   static method test(self::Test2* t) → void {
-    core::int* v1 = let final self::Test2* #t13 = t in #t13.==(null) ?{core::int*} null : #t13.{self::Test2::prop} = self::getInt();
-    core::num* v2 = let final self::Test2* #t14 = t in #t14.==(null) ?{core::num*} null : #t14.{self::Test2::prop} = self::getNum();
-    core::double* v3 = let final self::Test2* #t15 = t in #t15.==(null) ?{core::double*} null : #t15.{self::Test2::prop} = self::getDouble();
+    core::int* v1 = let final self::Test2* #t13 = t in #t13.{core::Object::==}(null) ?{core::int*} null : #t13.{self::Test2::prop} = self::getInt();
+    core::num* v2 = let final self::Test2* #t14 = t in #t14.{core::Object::==}(null) ?{core::num*} null : #t14.{self::Test2::prop} = self::getNum();
+    core::double* v3 = let final self::Test2* #t15 = t in #t15.{core::Object::==}(null) ?{core::double*} null : #t15.{self::Test2::prop} = self::getDouble();
     core::num* v4 = let final self::Test2* #t16 = t in #t16.==(null) ?{core::num*} null : let final core::num* #t17 = #t16.{self::Test2::prop} in #t17.{core::num::==}(null) ?{core::num*} #t16.{self::Test2::prop} = self::getInt() : #t17;
     core::num* v5 = let final self::Test2* #t18 = t in #t18.==(null) ?{core::num*} null : let final core::num* #t19 = #t18.{self::Test2::prop} in #t19.{core::num::==}(null) ?{core::num*} #t18.{self::Test2::prop} = self::getNum() : #t19;
     core::num* v6 = let final self::Test2* #t20 = t in #t20.==(null) ?{core::num*} null : let final core::num* #t21 = #t20.{self::Test2::prop} in #t21.{core::num::==}(null) ?{core::num*} #t20.{self::Test2::prop} = self::getDouble() : #t21;
@@ -43,8 +43,8 @@
     : super core::Object::•()
     ;
   static method test3(self::Test3* t) → void {
-    core::num* v2 = let final self::Test3* #t29 = t in #t29.==(null) ?{core::num*} null : #t29.{self::Test3::prop} = self::getNum() as{TypeError} core::double*;
-    core::double* v3 = let final self::Test3* #t30 = t in #t30.==(null) ?{core::double*} null : #t30.{self::Test3::prop} = self::getDouble();
+    core::num* v2 = let final self::Test3* #t29 = t in #t29.{core::Object::==}(null) ?{core::num*} null : #t29.{self::Test3::prop} = self::getNum() as{TypeError} core::double*;
+    core::double* v3 = let final self::Test3* #t30 = t in #t30.{core::Object::==}(null) ?{core::double*} null : #t30.{self::Test3::prop} = self::getDouble();
     core::num* v5 = let final self::Test3* #t31 = t in #t31.==(null) ?{core::num*} null : let final core::double* #t32 = #t31.{self::Test3::prop} in #t32.{core::num::==}(null) ?{core::num*} #t31.{self::Test3::prop} = self::getNum() as{TypeError} core::double* : #t32;
     core::double* v6 = let final self::Test3* #t33 = t in #t33.==(null) ?{core::double*} null : let final core::double* #t34 = #t33.{self::Test3::prop} in #t34.{core::num::==}(null) ?{core::double*} #t33.{self::Test3::prop} = self::getDouble() : #t34;
     core::double* v7 = let final self::Test3* #t35 = t in #t35.==(null) ?{core::double*} null : #t35.{self::Test3::prop} = #t35.{self::Test3::prop}.{core::double::+}(self::getInt());
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart
index 607cd37..428268a 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart
@@ -25,24 +25,53 @@
 class Test extends Base {
   void test() {
     super. /*@target=Base::member*/ member = /*@ typeArgs=B* */ f();
-    super. /*@target=Base::member*/ member ??= /*@ typeArgs=B* */ f();
-    super. /*@target=Base::member*/ member += /*@ typeArgs=dynamic */ f();
-    super. /*@target=Base::member*/ member *= /*@ typeArgs=dynamic */ f();
-    super. /*@target=Base::member*/ member &= /*@ typeArgs=dynamic */ f();
-    --super. /*@target=Base::member*/ member;
-    super. /*@target=Base::member*/ member--;
+
+    super. /*@target=Base::member*/ /*@target=Base::member*/ member
+        /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
+    super. /*@target=Base::member*/ /*@target=Base::member*/ member
+        /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+    super. /*@target=Base::member*/ /*@target=Base::member*/ member
+        /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+    super. /*@target=Base::member*/ /*@target=Base::member*/ member
+        /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+    /*@ target=B::- */ --super
+        . /*@target=Base::member*/ /*@target=Base::member*/ member;
+
+    super. /*@target=Base::member*/ /*@target=Base::member*/ member
+        /*@ target=B::- */ --;
+
     var /*@ type=B* */ v1 =
         super. /*@target=Base::member*/ member = /*@ typeArgs=B* */ f();
+
     var /*@ type=B* */ v2 =
-        super. /*@target=Base::member*/ member ??= /*@ typeArgs=B* */ f();
+        super. /*@target=Base::member*/ /*@target=Base::member*/ member
+            /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
     var /*@ type=A* */ v3 =
-        super. /*@target=Base::member*/ member += /*@ typeArgs=dynamic */ f();
+        super. /*@target=Base::member*/ /*@target=Base::member*/ member
+            /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
     var /*@ type=B* */ v4 =
-        super. /*@target=Base::member*/ member *= /*@ typeArgs=dynamic */ f();
+        super. /*@target=Base::member*/ /*@target=Base::member*/ member
+            /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
     var /*@ type=C* */ v5 =
-        super. /*@target=Base::member*/ member &= /*@ typeArgs=dynamic */ f();
-    var /*@ type=B* */ v6 = --super. /*@target=Base::member*/ member;
-    var /*@ type=B* */ v7 = super. /*@target=Base::member*/ member--;
+        super. /*@target=Base::member*/ /*@target=Base::member*/ member
+            /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+    var /*@ type=B* */ v6 = /*@ target=B::- */ --super
+        .
+        /*@target=Base::member*/ /*@target=Base::member*/ member;
+
+    var /*@ type=B* */ v7 = super
+            .
+            /*@ type=B* */ /*@target=Base::member*/ /*@target=Base::member*/
+            member
+        /*@ type=B* */ /*@ target=B::- */ --;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart.strong.expect
index 18c1122..eb317ce 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart.strong.expect
@@ -38,16 +38,16 @@
   method test() → void {
     super.{self::Base::member} = self::f<self::B*>();
     super.{self::Base::member}.{core::Object::==}(null) ?{self::B*} super.{self::Base::member} = self::f<self::B*>() : null;
-    super.{self::Base::member} = super.{self::Base::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-    super.{self::Base::member} = super.{self::Base::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    super.{self::Base::member} = super.{self::Base::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    super.{self::Base::member} = super.{self::Base::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    super.{self::Base::member} = super.{self::Base::member}.{self::B::*}(self::f<self::B*>());
+    super.{self::Base::member} = super.{self::Base::member}.{self::B::&}(self::f<self::A*>());
     super.{self::Base::member} = super.{self::Base::member}.{self::B::-}(1);
     super.{self::Base::member} = super.{self::Base::member}.{self::B::-}(1);
     self::B* v1 = super.{self::Base::member} = self::f<self::B*>();
     self::B* v2 = let final self::B* #t1 = super.{self::Base::member} in #t1.{core::Object::==}(null) ?{self::B*} super.{self::Base::member} = self::f<self::B*>() : #t1;
-    self::A* v3 = super.{self::Base::member} = super.{self::Base::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-    self::B* v4 = super.{self::Base::member} = super.{self::Base::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    self::C* v5 = super.{self::Base::member} = super.{self::Base::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    self::A* v3 = super.{self::Base::member} = super.{self::Base::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    self::B* v4 = super.{self::Base::member} = super.{self::Base::member}.{self::B::*}(self::f<self::B*>());
+    self::C* v5 = super.{self::Base::member} = super.{self::Base::member}.{self::B::&}(self::f<self::A*>());
     self::B* v6 = super.{self::Base::member} = super.{self::Base::member}.{self::B::-}(1);
     self::B* v7 = let final self::B* #t2 = super.{self::Base::member} in let final self::B* #t3 = super.{self::Base::member} = #t2.{self::B::-}(1) in #t2;
   }
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart.strong.transformed.expect
index 18c1122..eb317ce 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart.strong.transformed.expect
@@ -38,16 +38,16 @@
   method test() → void {
     super.{self::Base::member} = self::f<self::B*>();
     super.{self::Base::member}.{core::Object::==}(null) ?{self::B*} super.{self::Base::member} = self::f<self::B*>() : null;
-    super.{self::Base::member} = super.{self::Base::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-    super.{self::Base::member} = super.{self::Base::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    super.{self::Base::member} = super.{self::Base::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    super.{self::Base::member} = super.{self::Base::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    super.{self::Base::member} = super.{self::Base::member}.{self::B::*}(self::f<self::B*>());
+    super.{self::Base::member} = super.{self::Base::member}.{self::B::&}(self::f<self::A*>());
     super.{self::Base::member} = super.{self::Base::member}.{self::B::-}(1);
     super.{self::Base::member} = super.{self::Base::member}.{self::B::-}(1);
     self::B* v1 = super.{self::Base::member} = self::f<self::B*>();
     self::B* v2 = let final self::B* #t1 = super.{self::Base::member} in #t1.{core::Object::==}(null) ?{self::B*} super.{self::Base::member} = self::f<self::B*>() : #t1;
-    self::A* v3 = super.{self::Base::member} = super.{self::Base::member}.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-    self::B* v4 = super.{self::Base::member} = super.{self::Base::member}.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-    self::C* v5 = super.{self::Base::member} = super.{self::Base::member}.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+    self::A* v3 = super.{self::Base::member} = super.{self::Base::member}.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+    self::B* v4 = super.{self::Base::member} = super.{self::Base::member}.{self::B::*}(self::f<self::B*>());
+    self::C* v5 = super.{self::Base::member} = super.{self::Base::member}.{self::B::&}(self::f<self::A*>());
     self::B* v6 = super.{self::Base::member} = super.{self::Base::member}.{self::B::-}(1);
     self::B* v7 = let final self::B* #t2 = super.{self::Base::member} in let final self::B* #t3 = super.{self::Base::member} = #t2.{self::B::-}(1) in #t2;
   }
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_super_upwards.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_property_super_upwards.dart
index 470276a..d236e96 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_super_upwards.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_super_upwards.dart
@@ -17,37 +17,79 @@
 
 class Test1 extends Base {
   void test() {
-    var /*@ type=int* */ v1 = super. /*@target=Base::intProp*/ intProp = getInt();
-    var /*@ type=num* */ v2 = super. /*@target=Base::intProp*/ intProp = getNum();
+    var /*@ type=int* */ v1 =
+        super. /*@target=Base::intProp*/ intProp = getInt();
+
+    var /*@ type=num* */ v2 =
+        super. /*@target=Base::intProp*/ intProp = getNum();
+
     var /*@ type=int* */ v4 =
-        super. /*@target=Base::intProp*/ intProp ??= getInt();
+        super. /*@target=Base::intProp*/ /*@target=Base::intProp*/ intProp
+            /*@ target=num::== */ ??= getInt();
+
     var /*@ type=num* */ v5 =
-        super. /*@target=Base::intProp*/ intProp ??= getNum();
-    var /*@ type=int* */ v7 = super. /*@target=Base::intProp*/ intProp += getInt();
-    var /*@ type=num* */ v8 = super. /*@target=Base::intProp*/ intProp += getNum();
-    var /*@ type=int* */ v10 = ++super. /*@target=Base::intProp*/ intProp;
-    var /*@ type=int* */ v11 = super. /*@target=Base::intProp*/ intProp++;
+        super. /*@target=Base::intProp*/ /*@target=Base::intProp*/ intProp
+            /*@ target=num::== */ ??= getNum();
+
+    var /*@ type=int* */ v7 =
+        super. /*@target=Base::intProp*/ /*@target=Base::intProp*/ intProp
+            /*@ target=num::+ */ += getInt();
+
+    var /*@ type=num* */ v8 =
+        super. /*@target=Base::intProp*/ /*@target=Base::intProp*/ intProp
+            /*@ target=num::+ */ += getNum();
+
+    var /*@ type=int* */ v10 = /*@ target=num::+ */ ++super
+        . /*@target=Base::intProp*/ /*@target=Base::intProp*/ intProp;
+
+    var /*@ type=int* */ v11 = super
+            . /*@ type=int* */ /*@target=Base::intProp*/ /*@target=Base::intProp*/
+            intProp
+        /*@ type=int* */ /*@ target=num::+ */ ++;
   }
 }
 
 class Test2 extends Base {
   void test() {
-    var /*@ type=int* */ v1 = super. /*@target=Base::numProp*/ numProp = getInt();
-    var /*@ type=num* */ v2 = super. /*@target=Base::numProp*/ numProp = getNum();
+    var /*@ type=int* */ v1 =
+        super. /*@target=Base::numProp*/ numProp = getInt();
+
+    var /*@ type=num* */ v2 =
+        super. /*@target=Base::numProp*/ numProp = getNum();
+
     var /*@ type=double* */ v3 =
         super. /*@target=Base::numProp*/ numProp = getDouble();
+
     var /*@ type=num* */ v4 =
-        super. /*@target=Base::numProp*/ numProp ??= getInt();
+        super. /*@target=Base::numProp*/ /*@target=Base::numProp*/ numProp
+            /*@ target=num::== */ ??= getInt();
+
     var /*@ type=num* */ v5 =
-        super. /*@target=Base::numProp*/ numProp ??= getNum();
+        super. /*@target=Base::numProp*/ /*@target=Base::numProp*/ numProp
+            /*@ target=num::== */ ??= getNum();
+
     var /*@ type=num* */ v6 =
-        super. /*@target=Base::numProp*/ numProp ??= getDouble();
-    var /*@ type=num* */ v7 = super. /*@target=Base::numProp*/ numProp += getInt();
-    var /*@ type=num* */ v8 = super. /*@target=Base::numProp*/ numProp += getNum();
+        super. /*@target=Base::numProp*/ /*@target=Base::numProp*/ numProp
+            /*@ target=num::== */ ??= getDouble();
+
+    var /*@ type=num* */ v7 =
+        super. /*@target=Base::numProp*/ /*@target=Base::numProp*/ numProp
+            /*@ target=num::+ */ += getInt();
+
+    var /*@ type=num* */ v8 =
+        super. /*@target=Base::numProp*/ /*@target=Base::numProp*/ numProp
+            /*@ target=num::+ */ += getNum();
+
     var /*@ type=num* */ v9 =
-        super. /*@target=Base::numProp*/ numProp += getDouble();
-    var /*@ type=num* */ v10 = ++super. /*@target=Base::numProp*/ numProp;
-    var /*@ type=num* */ v11 = super. /*@target=Base::numProp*/ numProp++;
+        super. /*@target=Base::numProp*/ /*@target=Base::numProp*/ numProp
+            /*@ target=num::+ */ += getDouble();
+
+    var /*@ type=num* */ v10 = /*@ target=num::+ */ ++super
+        . /*@target=Base::numProp*/ /*@target=Base::numProp*/ numProp;
+
+    var /*@ type=num* */ v11 = super
+        . /*@ type=num* */ /*@target=Base::numProp*/ /*@target=Base::numProp*/
+        numProp /*@ type=num* */ /*@ target=num::+ */ ++;
   }
 }
 
@@ -55,20 +97,38 @@
   void test3() {
     var /*@ type=num* */ v2 =
         super. /*@target=Base::doubleProp*/ doubleProp = getNum();
+
     var /*@ type=double* */ v3 =
         super. /*@target=Base::doubleProp*/ doubleProp = getDouble();
-    var /*@ type=num* */ v5 =
-        super. /*@target=Base::doubleProp*/ doubleProp ??= getNum();
-    var /*@ type=double* */ v6 =
-        super. /*@target=Base::doubleProp*/ doubleProp ??= getDouble();
-    var /*@ type=double* */ v7 =
-        super. /*@target=Base::doubleProp*/ doubleProp += getInt();
-    var /*@ type=double* */ v8 =
-        super. /*@target=Base::doubleProp*/ doubleProp += getNum();
-    var /*@ type=double* */ v9 =
-        super. /*@target=Base::doubleProp*/ doubleProp += getDouble();
-    var /*@ type=double* */ v10 = ++super. /*@target=Base::doubleProp*/ doubleProp;
-    var /*@ type=double* */ v11 = super. /*@target=Base::doubleProp*/ doubleProp++;
+
+    var /*@ type=num* */ v5 = super
+            . /*@target=Base::doubleProp*/ /*@target=Base::doubleProp*/ doubleProp
+        /*@ target=num::== */ ??= getNum();
+
+    var /*@ type=double* */ v6 = super
+            . /*@target=Base::doubleProp*/ /*@target=Base::doubleProp*/ doubleProp
+        /*@ target=num::== */ ??= getDouble();
+
+    var /*@ type=double* */ v7 = super
+        . /*@target=Base::doubleProp*/ /*@target=Base::doubleProp*/
+        doubleProp /*@ target=double::+ */ += getInt();
+
+    var /*@ type=double* */ v8 = super
+        . /*@target=Base::doubleProp*/ /*@target=Base::doubleProp*/
+        doubleProp /*@ target=double::+ */ += getNum();
+
+    var /*@ type=double* */ v9 = super
+        . /*@target=Base::doubleProp*/ /*@target=Base::doubleProp*/
+        doubleProp /*@ target=double::+ */ += getDouble();
+
+    var /*@ type=double* */ v10 =
+        /*@ target=double::+ */ ++super
+            . /*@target=Base::doubleProp*/ /*@target=Base::doubleProp*/
+            doubleProp;
+
+    var /*@ type=double* */ v11 = super
+        . /*@ type=double* */ /*@target=Base::doubleProp*/ /*@target=Base::doubleProp*/
+        doubleProp /*@ type=double* */ /*@ target=double::+ */ ++;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_upwards.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_property_upwards.dart
index 5ade9c5..502a144 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_upwards.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_upwards.dart
@@ -15,12 +15,24 @@
   static void test(Test1 t) {
     var /*@ type=int* */ v1 = t. /*@target=Test1::prop*/ prop = getInt();
     var /*@ type=num* */ v2 = t. /*@target=Test1::prop*/ prop = getNum();
-    var /*@ type=int* */ v4 = t. /*@target=Test1::prop*/ prop ??= getInt();
-    var /*@ type=num* */ v5 = t. /*@target=Test1::prop*/ prop ??= getNum();
-    var /*@ type=int* */ v7 = t. /*@target=Test1::prop*/ prop += getInt();
-    var /*@ type=num* */ v8 = t. /*@target=Test1::prop*/ prop += getNum();
-    var /*@ type=int* */ v10 = ++t. /*@target=Test1::prop*/ prop;
-    var /*@ type=int* */ v11 = t. /*@target=Test1::prop*/ prop++;
+    var /*@ type=int* */ v4 = /*@ type=Test1* */ t
+            . /*@target=Test1::prop*/ /*@target=Test1::prop*/ prop
+        /*@target=num::==*/ ??= getInt();
+    var /*@ type=num* */ v5 = /*@ type=Test1* */ t
+            . /*@target=Test1::prop*/ /*@target=Test1::prop*/ prop
+        /*@target=num::==*/ ??= getNum();
+    var /*@ type=int* */ v7 = /*@ type=Test1* */ t
+            . /*@target=Test1::prop*/ /*@target=Test1::prop*/ prop
+        /*@ target=num::+ */ += getInt();
+    var /*@ type=num* */ v8 = /*@ type=Test1* */ t
+            . /*@target=Test1::prop*/ /*@target=Test1::prop*/ prop
+        /*@ target=num::+ */ += getNum();
+    var /*@ type=int* */ v10 = /*@ target=num::+ */ ++ /*@ type=Test1* */ t
+        . /*@target=Test1::prop*/ /*@target=Test1::prop*/ prop;
+    var /*@ type=int* */ v11 =
+        /*@ type=Test1* */ t
+            . /*@ type=int* */ /*@target=Test1::prop*/ /*@target=Test1::prop*/
+            prop /*@ type=int* */ /*@ target=num::+ */ ++;
   }
 }
 
@@ -31,14 +43,30 @@
     var /*@ type=int* */ v1 = t. /*@target=Test2::prop*/ prop = getInt();
     var /*@ type=num* */ v2 = t. /*@target=Test2::prop*/ prop = getNum();
     var /*@ type=double* */ v3 = t. /*@target=Test2::prop*/ prop = getDouble();
-    var /*@ type=num* */ v4 = t. /*@target=Test2::prop*/ prop ??= getInt();
-    var /*@ type=num* */ v5 = t. /*@target=Test2::prop*/ prop ??= getNum();
-    var /*@ type=num* */ v6 = t. /*@target=Test2::prop*/ prop ??= getDouble();
-    var /*@ type=num* */ v7 = t. /*@target=Test2::prop*/ prop += getInt();
-    var /*@ type=num* */ v8 = t. /*@target=Test2::prop*/ prop += getNum();
-    var /*@ type=num* */ v9 = t. /*@target=Test2::prop*/ prop += getDouble();
-    var /*@ type=num* */ v10 = ++t. /*@target=Test2::prop*/ prop;
-    var /*@ type=num* */ v11 = t. /*@target=Test2::prop*/ prop++;
+    var /*@ type=num* */ v4 = /*@ type=Test2* */ t
+            . /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+        /*@target=num::==*/ ??= getInt();
+    var /*@ type=num* */ v5 = /*@ type=Test2* */ t
+            . /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+        /*@target=num::==*/ ??= getNum();
+    var /*@ type=num* */ v6 = /*@ type=Test2* */ t
+            . /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+        /*@target=num::==*/ ??= getDouble();
+    var /*@ type=num* */ v7 = /*@ type=Test2* */ t
+            . /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+        /*@ target=num::+ */ += getInt();
+    var /*@ type=num* */ v8 = /*@ type=Test2* */ t
+            . /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+        /*@ target=num::+ */ += getNum();
+    var /*@ type=num* */ v9 = /*@ type=Test2* */ t
+            . /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop
+        /*@ target=num::+ */ += getDouble();
+    var /*@ type=num* */ v10 = /*@ target=num::+ */ ++ /*@ type=Test2* */ t
+        . /*@target=Test2::prop*/ /*@target=Test2::prop*/ prop;
+    var /*@ type=num* */ v11 =
+        /*@ type=Test2* */ t
+            . /*@ type=num* */ /*@target=Test2::prop*/ /*@target=Test2::prop*/
+            prop /*@ type=num* */ /*@ target=num::+ */ ++;
   }
 }
 
@@ -48,13 +76,27 @@
   static void test3(Test3 t) {
     var /*@ type=num* */ v2 = t. /*@target=Test3::prop*/ prop = getNum();
     var /*@ type=double* */ v3 = t. /*@target=Test3::prop*/ prop = getDouble();
-    var /*@ type=num* */ v5 = t. /*@target=Test3::prop*/ prop ??= getNum();
-    var /*@ type=double* */ v6 = t. /*@target=Test3::prop*/ prop ??= getDouble();
-    var /*@ type=double* */ v7 = t. /*@target=Test3::prop*/ prop += getInt();
-    var /*@ type=double* */ v8 = t. /*@target=Test3::prop*/ prop += getNum();
-    var /*@ type=double* */ v9 = t. /*@target=Test3::prop*/ prop += getDouble();
-    var /*@ type=double* */ v10 = ++t. /*@target=Test3::prop*/ prop;
-    var /*@ type=double* */ v11 = t. /*@target=Test3::prop*/ prop++;
+    var /*@ type=num* */ v5 = /*@ type=Test3* */ t
+            . /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop
+        /*@target=num::==*/ ??= getNum();
+    var /*@ type=double* */ v6 = /*@ type=Test3* */ t
+            . /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop
+        /*@target=num::==*/ ??= getDouble();
+    var /*@ type=double* */ v7 = /*@ type=Test3* */ t
+            . /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop
+        /*@ target=double::+ */ += getInt();
+    var /*@ type=double* */ v8 = /*@ type=Test3* */ t
+            . /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop
+        /*@ target=double::+ */ += getNum();
+    var /*@ type=double* */ v9 = /*@ type=Test3* */ t
+            . /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop
+        /*@ target=double::+ */ += getDouble();
+    var /*@ type=double* */ v10 = /*@ target=double::+ */ ++ /*@ type=Test3* */ t
+        . /*@target=Test3::prop*/ /*@target=Test3::prop*/ prop;
+    var /*@ type=double* */ v11 =
+        /*@ type=Test3* */ t
+            . /*@ type=double* */ /*@target=Test3::prop*/ /*@target=Test3::prop*/
+            prop /*@ type=double* */ /*@ target=double::+ */ ++;
   }
 }
 
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_static.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_static.dart
index 1a832b3..33bd5fe 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_static.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_static.dart
@@ -24,36 +24,72 @@
 
 void test_topLevelVariable() {
   topLevelVariable = /*@ typeArgs=B* */ f();
-  topLevelVariable ??= /*@ typeArgs=B* */ f();
-  topLevelVariable += /*@ typeArgs=dynamic */ f();
-  topLevelVariable *= /*@ typeArgs=dynamic */ f();
-  topLevelVariable &= /*@ typeArgs=dynamic */ f();
-  --topLevelVariable;
-  topLevelVariable--;
+
+  topLevelVariable /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
+  topLevelVariable /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+  topLevelVariable /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+  topLevelVariable /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+  /*@ target=B::- */ --topLevelVariable;
+
+  topLevelVariable /*@ target=B::- */ --;
+
   var /*@ type=B* */ v1 = topLevelVariable = /*@ typeArgs=B* */ f();
-  var /*@ type=B* */ v2 = topLevelVariable ??= /*@ typeArgs=B* */ f();
-  var /*@ type=A* */ v3 = topLevelVariable += /*@ typeArgs=dynamic */ f();
-  var /*@ type=B* */ v4 = topLevelVariable *= /*@ typeArgs=dynamic */ f();
-  var /*@ type=C* */ v5 = topLevelVariable &= /*@ typeArgs=dynamic */ f();
-  var /*@ type=B* */ v6 = --topLevelVariable;
-  var /*@ type=B* */ v7 = topLevelVariable--;
+
+  var /*@ type=B* */ v2 =
+      topLevelVariable /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
+  var /*@ type=A* */ v3 =
+      topLevelVariable /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+  var /*@ type=B* */ v4 =
+      topLevelVariable /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+  var /*@ type=C* */ v5 =
+      topLevelVariable /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+  var /*@ type=B* */ v6 = /*@ target=B::- */ --topLevelVariable;
+
+  var /*@ type=B* */ v7 = /*@ type=B* */ topLevelVariable
+      /*@ type=B* */ /*@ target=B::- */ --;
 }
 
 void test_staticVariable() {
   B.staticVariable = /*@ typeArgs=B* */ f();
-  B.staticVariable ??= /*@ typeArgs=B* */ f();
-  B.staticVariable += /*@ typeArgs=dynamic */ f();
-  B.staticVariable *= /*@ typeArgs=dynamic */ f();
-  B.staticVariable &= /*@ typeArgs=dynamic */ f();
-  --B.staticVariable;
-  B.staticVariable--;
+
+  B.staticVariable /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
+  B.staticVariable /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+  B.staticVariable /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+  B.staticVariable /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+  /*@ target=B::- */ --B.staticVariable;
+
+  B.staticVariable /*@ target=B::- */ --;
+
   var /*@ type=B* */ v1 = B.staticVariable = /*@ typeArgs=B* */ f();
-  var /*@ type=B* */ v2 = B.staticVariable ??= /*@ typeArgs=B* */ f();
-  var /*@ type=A* */ v3 = B.staticVariable += /*@ typeArgs=dynamic */ f();
-  var /*@ type=B* */ v4 = B.staticVariable *= /*@ typeArgs=dynamic */ f();
-  var /*@ type=C* */ v5 = B.staticVariable &= /*@ typeArgs=dynamic */ f();
-  var /*@ type=B* */ v6 = --B.staticVariable;
-  var /*@ type=B* */ v7 = B.staticVariable--;
+
+  var /*@ type=B* */ v2 =
+      B.staticVariable /*@ target=Object::== */ ??= /*@ typeArgs=B* */ f();
+
+  var /*@ type=A* */ v3 =
+      B.staticVariable /*@ target=B::+ */ += /*@ typeArgs=C* */ f();
+
+  var /*@ type=B* */ v4 =
+      B.staticVariable /*@ target=B::* */ *= /*@ typeArgs=B* */ f();
+
+  var /*@ type=C* */ v5 =
+      B.staticVariable /*@ target=B::& */ &= /*@ typeArgs=A* */ f();
+
+  var /*@ type=B* */ v6 = /*@ target=B::- */ --B.staticVariable;
+
+  var /*@ type=B* */ v7 =
+      B. /*@ type=B* */ staticVariable /*@ type=B* */ /*@ target=B::- */ --;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_static.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_static.dart.strong.expect
index 00189a5..2c07ffd 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_static.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_static.dart.strong.expect
@@ -32,32 +32,32 @@
 static method test_topLevelVariable() → void {
   self::topLevelVariable = self::f<self::B*>();
   self::topLevelVariable.{core::Object::==}(null) ?{self::B*} self::topLevelVariable = self::f<self::B*>() : null;
-  self::topLevelVariable = self::topLevelVariable.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-  self::topLevelVariable = self::topLevelVariable.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::topLevelVariable = self::topLevelVariable.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::topLevelVariable = self::topLevelVariable.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::topLevelVariable = self::topLevelVariable.{self::B::*}(self::f<self::B*>());
+  self::topLevelVariable = self::topLevelVariable.{self::B::&}(self::f<self::A*>());
   self::topLevelVariable = self::topLevelVariable.{self::B::-}(1);
   self::topLevelVariable = self::topLevelVariable.{self::B::-}(1);
   self::B* v1 = self::topLevelVariable = self::f<self::B*>();
   self::B* v2 = let final self::B* #t1 = self::topLevelVariable in #t1.{core::Object::==}(null) ?{self::B*} self::topLevelVariable = self::f<self::B*>() : #t1;
-  self::A* v3 = self::topLevelVariable = self::topLevelVariable.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-  self::B* v4 = self::topLevelVariable = self::topLevelVariable.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::C* v5 = self::topLevelVariable = self::topLevelVariable.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::A* v3 = self::topLevelVariable = self::topLevelVariable.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::B* v4 = self::topLevelVariable = self::topLevelVariable.{self::B::*}(self::f<self::B*>());
+  self::C* v5 = self::topLevelVariable = self::topLevelVariable.{self::B::&}(self::f<self::A*>());
   self::B* v6 = self::topLevelVariable = self::topLevelVariable.{self::B::-}(1);
   self::B* v7 = let final self::B* #t2 = self::topLevelVariable in let final self::B* #t3 = self::topLevelVariable = #t2.{self::B::-}(1) in #t2;
 }
 static method test_staticVariable() → void {
   self::B::staticVariable = self::f<self::B*>();
   self::B::staticVariable.{core::Object::==}(null) ?{self::B*} self::B::staticVariable = self::f<self::B*>() : null;
-  self::B::staticVariable = self::B::staticVariable.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-  self::B::staticVariable = self::B::staticVariable.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::B::staticVariable = self::B::staticVariable.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::B::staticVariable = self::B::staticVariable.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::B::staticVariable = self::B::staticVariable.{self::B::*}(self::f<self::B*>());
+  self::B::staticVariable = self::B::staticVariable.{self::B::&}(self::f<self::A*>());
   self::B::staticVariable = self::B::staticVariable.{self::B::-}(1);
   self::B::staticVariable = self::B::staticVariable.{self::B::-}(1);
   self::B* v1 = self::B::staticVariable = self::f<self::B*>();
   self::B* v2 = let final self::B* #t4 = self::B::staticVariable in #t4.{core::Object::==}(null) ?{self::B*} self::B::staticVariable = self::f<self::B*>() : #t4;
-  self::A* v3 = self::B::staticVariable = self::B::staticVariable.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-  self::B* v4 = self::B::staticVariable = self::B::staticVariable.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::C* v5 = self::B::staticVariable = self::B::staticVariable.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::A* v3 = self::B::staticVariable = self::B::staticVariable.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::B* v4 = self::B::staticVariable = self::B::staticVariable.{self::B::*}(self::f<self::B*>());
+  self::C* v5 = self::B::staticVariable = self::B::staticVariable.{self::B::&}(self::f<self::A*>());
   self::B* v6 = self::B::staticVariable = self::B::staticVariable.{self::B::-}(1);
   self::B* v7 = let final self::B* #t5 = self::B::staticVariable in let final self::B* #t6 = self::B::staticVariable = #t5.{self::B::-}(1) in #t5;
 }
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_static.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_static.dart.strong.transformed.expect
index 00189a5..2c07ffd 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_static.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_static.dart.strong.transformed.expect
@@ -32,32 +32,32 @@
 static method test_topLevelVariable() → void {
   self::topLevelVariable = self::f<self::B*>();
   self::topLevelVariable.{core::Object::==}(null) ?{self::B*} self::topLevelVariable = self::f<self::B*>() : null;
-  self::topLevelVariable = self::topLevelVariable.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-  self::topLevelVariable = self::topLevelVariable.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::topLevelVariable = self::topLevelVariable.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::topLevelVariable = self::topLevelVariable.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::topLevelVariable = self::topLevelVariable.{self::B::*}(self::f<self::B*>());
+  self::topLevelVariable = self::topLevelVariable.{self::B::&}(self::f<self::A*>());
   self::topLevelVariable = self::topLevelVariable.{self::B::-}(1);
   self::topLevelVariable = self::topLevelVariable.{self::B::-}(1);
   self::B* v1 = self::topLevelVariable = self::f<self::B*>();
   self::B* v2 = let final self::B* #t1 = self::topLevelVariable in #t1.{core::Object::==}(null) ?{self::B*} self::topLevelVariable = self::f<self::B*>() : #t1;
-  self::A* v3 = self::topLevelVariable = self::topLevelVariable.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-  self::B* v4 = self::topLevelVariable = self::topLevelVariable.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::C* v5 = self::topLevelVariable = self::topLevelVariable.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::A* v3 = self::topLevelVariable = self::topLevelVariable.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::B* v4 = self::topLevelVariable = self::topLevelVariable.{self::B::*}(self::f<self::B*>());
+  self::C* v5 = self::topLevelVariable = self::topLevelVariable.{self::B::&}(self::f<self::A*>());
   self::B* v6 = self::topLevelVariable = self::topLevelVariable.{self::B::-}(1);
   self::B* v7 = let final self::B* #t2 = self::topLevelVariable in let final self::B* #t3 = self::topLevelVariable = #t2.{self::B::-}(1) in #t2;
 }
 static method test_staticVariable() → void {
   self::B::staticVariable = self::f<self::B*>();
   self::B::staticVariable.{core::Object::==}(null) ?{self::B*} self::B::staticVariable = self::f<self::B*>() : null;
-  self::B::staticVariable = self::B::staticVariable.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-  self::B::staticVariable = self::B::staticVariable.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::B::staticVariable = self::B::staticVariable.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::B::staticVariable = self::B::staticVariable.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::B::staticVariable = self::B::staticVariable.{self::B::*}(self::f<self::B*>());
+  self::B::staticVariable = self::B::staticVariable.{self::B::&}(self::f<self::A*>());
   self::B::staticVariable = self::B::staticVariable.{self::B::-}(1);
   self::B::staticVariable = self::B::staticVariable.{self::B::-}(1);
   self::B* v1 = self::B::staticVariable = self::f<self::B*>();
   self::B* v2 = let final self::B* #t4 = self::B::staticVariable in #t4.{core::Object::==}(null) ?{self::B*} self::B::staticVariable = self::f<self::B*>() : #t4;
-  self::A* v3 = self::B::staticVariable = self::B::staticVariable.{self::B::+}(self::f<dynamic>() as{TypeError} self::C*) as{TypeError} self::B*;
-  self::B* v4 = self::B::staticVariable = self::B::staticVariable.{self::B::*}(self::f<dynamic>() as{TypeError} self::B*);
-  self::C* v5 = self::B::staticVariable = self::B::staticVariable.{self::B::&}(self::f<dynamic>() as{TypeError} self::A*);
+  self::A* v3 = self::B::staticVariable = self::B::staticVariable.{self::B::+}(self::f<self::C*>()) as{TypeError} self::B*;
+  self::B* v4 = self::B::staticVariable = self::B::staticVariable.{self::B::*}(self::f<self::B*>());
+  self::C* v5 = self::B::staticVariable = self::B::staticVariable.{self::B::&}(self::f<self::A*>());
   self::B* v6 = self::B::staticVariable = self::B::staticVariable.{self::B::-}(1);
   self::B* v7 = let final self::B* #t5 = self::B::staticVariable in let final self::B* #t6 = self::B::staticVariable = #t5.{self::B::-}(1) in #t5;
 }
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_static_upwards.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_static_upwards.dart
index 93419da..4f08b48 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_static_upwards.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_static_upwards.dart
@@ -15,39 +15,71 @@
 
 void test1() {
   var /*@ type=int* */ v1 = topLevelInt = getInt();
+
   var /*@ type=num* */ v2 = topLevelInt = getNum();
-  var /*@ type=int* */ v4 = topLevelInt ??= getInt();
-  var /*@ type=num* */ v5 = topLevelInt ??= getNum();
-  var /*@ type=int* */ v7 = topLevelInt += getInt();
-  var /*@ type=num* */ v8 = topLevelInt += getNum();
-  var /*@ type=int* */ v10 = ++topLevelInt;
-  var /*@ type=int* */ v11 = topLevelInt++;
+
+  var /*@ type=int* */ v4 = topLevelInt /*@ target=num::== */ ??= getInt();
+
+  var /*@ type=num* */ v5 = topLevelInt /*@ target=num::== */ ??= getNum();
+
+  var /*@ type=int* */ v7 = topLevelInt /*@ target=num::+ */ += getInt();
+
+  var /*@ type=num* */ v8 = topLevelInt /*@ target=num::+ */ += getNum();
+
+  var /*@ type=int* */ v10 = /*@ target=num::+ */ ++topLevelInt;
+
+  var /*@ type=int* */ v11 = /*@ type=int* */ topLevelInt
+      /*@ type=int* */ /*@ target=num::+ */ ++;
 }
 
 void test2() {
   var /*@ type=int* */ v1 = topLevelNum = getInt();
+
   var /*@ type=num* */ v2 = topLevelNum = getNum();
+
   var /*@ type=double* */ v3 = topLevelNum = getDouble();
-  var /*@ type=num* */ v4 = topLevelNum ??= getInt();
-  var /*@ type=num* */ v5 = topLevelNum ??= getNum();
-  var /*@ type=num* */ v6 = topLevelNum ??= getDouble();
-  var /*@ type=num* */ v7 = topLevelNum += getInt();
-  var /*@ type=num* */ v8 = topLevelNum += getNum();
-  var /*@ type=num* */ v9 = topLevelNum += getDouble();
-  var /*@ type=num* */ v10 = ++topLevelNum;
-  var /*@ type=num* */ v11 = topLevelNum++;
+
+  var /*@ type=num* */ v4 = topLevelNum /*@ target=num::== */ ??= getInt();
+
+  var /*@ type=num* */ v5 = topLevelNum /*@ target=num::== */ ??= getNum();
+
+  var /*@ type=num* */ v6 = topLevelNum /*@ target=num::== */ ??= getDouble();
+
+  var /*@ type=num* */ v7 = topLevelNum /*@ target=num::+ */ += getInt();
+
+  var /*@ type=num* */ v8 = topLevelNum /*@ target=num::+ */ += getNum();
+
+  var /*@ type=num* */ v9 = topLevelNum /*@ target=num::+ */ += getDouble();
+
+  var /*@ type=num* */ v10 = /*@ target=num::+ */ ++topLevelNum;
+
+  var /*@ type=num* */ v11 = /*@ type=num* */ topLevelNum
+      /*@ type=num* */ /*@ target=num::+ */ ++;
 }
 
 void test3() {
   var /*@ type=num* */ v2 = topLevelDouble = getNum();
+
   var /*@ type=double* */ v3 = topLevelDouble = getDouble();
-  var /*@ type=num* */ v5 = topLevelDouble ??= getNum();
-  var /*@ type=double* */ v6 = topLevelDouble ??= getDouble();
-  var /*@ type=double* */ v7 = topLevelDouble += getInt();
-  var /*@ type=double* */ v8 = topLevelDouble += getNum();
-  var /*@ type=double* */ v9 = topLevelDouble += getDouble();
-  var /*@ type=double* */ v10 = ++topLevelDouble;
-  var /*@ type=double* */ v11 = topLevelDouble++;
+
+  var /*@ type=num* */ v5 = topLevelDouble /*@ target=num::== */ ??= getNum();
+
+  var /*@ type=double* */ v6 =
+      topLevelDouble /*@ target=num::== */ ??= getDouble();
+
+  var /*@ type=double* */ v7 =
+      topLevelDouble /*@ target=double::+ */ += getInt();
+
+  var /*@ type=double* */ v8 =
+      topLevelDouble /*@ target=double::+ */ += getNum();
+
+  var /*@ type=double* */ v9 =
+      topLevelDouble /*@ target=double::+ */ += getDouble();
+
+  var /*@ type=double* */ v10 = /*@ target=double::+ */ ++topLevelDouble;
+
+  var /*@ type=double* */ v11 = /*@ type=double* */ topLevelDouble
+      /*@ type=double* */ /*@ target=double::+ */ ++;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart b/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart
index fd98fc2..af51b3b 100644
--- a/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart
+++ b/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart
@@ -20,6 +20,8 @@
 
 var a = new A();
 var x = a. /*@target=A::b*/ b. /*@target=B::c*/ c;
-var y = a. /*@target=A::b*/ b. /*@target=B::c*/ c ??= new D();
+var y =
+    a. /*@ type=B* */ /*@target=A::b*/ b. /*@target=B::c*/ /*@target=B::c*/ c
+        /*@target=Object::==*/ ??= new D();
 
 main() {}
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart b/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart
index e649aab..ac3418c 100644
--- a/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart
+++ b/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart
@@ -19,6 +19,7 @@
 
 var a = new A();
 var x = a. /*@target=A::b*/ b. /*@target=B::c*/ c;
-var y = a. /*@target=A::b*/ b. /*@target=B::c*/ c ??= new D();
+var y = a. /*@ type=B* */ /*@target=A::b*/ b
+    . /*@target=B::c*/ /*@target=B::c*/ c /*@target=Object::==*/ ??= new D();
 
 main() {}
diff --git a/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart b/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart
index 83fd2d8..f8811d5 100644
--- a/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart
+++ b/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart
@@ -5,7 +5,7 @@
 /*@testedFeatures=inference*/
 library test;
 
-var x = /*@ typeArgs=Null* */ [null];
+var x = /*@ typeArgs=Null? */ [null];
 
 main() {
   x;
diff --git a/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.outline.expect b/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.outline.expect
index efecb76..e4f67d0 100644
--- a/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.outline.expect
+++ b/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.outline.expect
@@ -2,6 +2,6 @@
 import self as self;
 import "dart:core" as core;
 
-static field core::List<core::Null*>* x;
+static field core::List<core::Null?>* x;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.strong.expect b/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.strong.expect
index 1b33259..aa63d12 100644
--- a/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-static field core::List<core::Null*>* x = <core::Null*>[null];
+static field core::List<core::Null?>* x = <core::Null?>[null];
 static method main() → dynamic {
   self::x;
 }
diff --git a/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.strong.transformed.expect
index 1b33259..aa63d12 100644
--- a/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-static field core::List<core::Null*>* x = <core::Null*>[null];
+static field core::List<core::Null?>* x = <core::Null?>[null];
 static method main() → dynamic {
   self::x;
 }
diff --git a/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart b/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart
index 17b5a27..03f228f 100644
--- a/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart
+++ b/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart
@@ -5,7 +5,7 @@
 /*@testedFeatures=inference*/
 library test;
 
-var x = /*@ typeArgs=Null*, Null* */ {null: null};
+var x = /*@ typeArgs=Null?, Null? */ {null: null};
 
 main() {
   x;
diff --git a/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.outline.expect b/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.outline.expect
index 0f28e73..f7f9db3 100644
--- a/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.outline.expect
+++ b/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.outline.expect
@@ -2,6 +2,6 @@
 import self as self;
 import "dart:core" as core;
 
-static field core::Map<core::Null*, core::Null*>* x;
+static field core::Map<core::Null?, core::Null?>* x;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.strong.expect b/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.strong.expect
index 79c64f0..4f1d6de 100644
--- a/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-static field core::Map<core::Null*, core::Null*>* x = <core::Null*, core::Null*>{null: null};
+static field core::Map<core::Null?, core::Null?>* x = <core::Null?, core::Null?>{null: null};
 static method main() → dynamic {
   self::x;
 }
diff --git a/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.strong.transformed.expect
index 79c64f0..4f1d6de 100644
--- a/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/map_literals_can_infer_null_top_level.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-static field core::Map<core::Null*, core::Null*>* x = <core::Null*, core::Null*>{null: null};
+static field core::Map<core::Null?, core::Null?>* x = <core::Null?, core::Null?>{null: null};
 static method main() → dynamic {
   self::x;
 }
diff --git a/pkg/front_end/testcases/inference_new/property_assign_combiner.dart b/pkg/front_end/testcases/inference_new/property_assign_combiner.dart
index b4c2286..c38f17d 100644
--- a/pkg/front_end/testcases/inference_new/property_assign_combiner.dart
+++ b/pkg/front_end/testcases/inference_new/property_assign_combiner.dart
@@ -32,19 +32,28 @@
 }
 
 void test1(G g) {
-  g. /*@target=G::target*/ target *= /*@ typeArgs=dynamic */ f();
+  /*@ type=G* */ g. /*@target=G::target*/ /*@target=G::target*/ target
+      /*@ target=A::* */ *=
+      /*@ typeArgs=D* */ f();
   var /*@ type=C* */ x =
-      g. /*@target=G::target*/ target *= /*@ typeArgs=dynamic */ f();
+      /*@ type=G* */ g. /*@target=G::target*/ /*@target=G::target*/ target
+          /*@ target=A::* */ *=
+          /*@ typeArgs=D* */ f();
 }
 
 void test2(G g) {
-  ++g. /*@target=G::target*/ target;
-  var /*@ type=C* */ x = ++g. /*@target=G::target*/ target;
+  /*@ target=A::+ */ ++ /*@ type=G* */ g
+      . /*@target=G::target*/ /*@target=G::target*/ target;
+  var /*@ type=C* */ x = /*@ target=A::+ */ ++ /*@ type=G* */ g
+      . /*@target=G::target*/ /*@target=G::target*/ target;
 }
 
 void test3(G g) {
-  g. /*@target=G::target*/ target++;
-  var /*@ type=A* */ x = g. /*@target=G::target*/ target++;
+  /*@ type=G* */ g
+      . /*@target=G::target*/ /*@target=G::target*/ target /*@ target=A::+ */ ++;
+  var /*@ type=A* */ x = /*@ type=G* */ g
+          . /*@ type=A* */ /*@target=G::target*/ /*@target=G::target*/ target
+      /*@ type=C* */ /*@ target=A::+ */ ++;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.strong.expect b/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.strong.expect
index 572f472..85a7b60 100644
--- a/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.strong.expect
@@ -51,8 +51,8 @@
 static method f<T extends core::Object* = dynamic>() → self::f::T*
   return null;
 static method test1(self::G* g) → void {
-  let final self::G* #t1 = g in #t1.{self::G::target} = #t1.{self::G::target}.{self::A::*}(self::f<dynamic>() as{TypeError} self::D*);
-  self::C* x = let final self::G* #t2 = g in #t2.{self::G::target} = #t2.{self::G::target}.{self::A::*}(self::f<dynamic>() as{TypeError} self::D*);
+  let final self::G* #t1 = g in #t1.{self::G::target} = #t1.{self::G::target}.{self::A::*}(self::f<self::D*>());
+  self::C* x = let final self::G* #t2 = g in #t2.{self::G::target} = #t2.{self::G::target}.{self::A::*}(self::f<self::D*>());
 }
 static method test2(self::G* g) → void {
   let final self::G* #t3 = g in #t3.{self::G::target} = #t3.{self::G::target}.{self::A::+}(1);
diff --git a/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.strong.transformed.expect
index 572f472..85a7b60 100644
--- a/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.strong.transformed.expect
@@ -51,8 +51,8 @@
 static method f<T extends core::Object* = dynamic>() → self::f::T*
   return null;
 static method test1(self::G* g) → void {
-  let final self::G* #t1 = g in #t1.{self::G::target} = #t1.{self::G::target}.{self::A::*}(self::f<dynamic>() as{TypeError} self::D*);
-  self::C* x = let final self::G* #t2 = g in #t2.{self::G::target} = #t2.{self::G::target}.{self::A::*}(self::f<dynamic>() as{TypeError} self::D*);
+  let final self::G* #t1 = g in #t1.{self::G::target} = #t1.{self::G::target}.{self::A::*}(self::f<self::D*>());
+  self::C* x = let final self::G* #t2 = g in #t2.{self::G::target} = #t2.{self::G::target}.{self::A::*}(self::f<self::D*>());
 }
 static method test2(self::G* g) → void {
   let final self::G* #t3 = g in #t3.{self::G::target} = #t3.{self::G::target}.{self::A::+}(1);
diff --git a/pkg/front_end/testcases/inference_new/static_assign_combiner.dart b/pkg/front_end/testcases/inference_new/static_assign_combiner.dart
index 2d57409..15084a1 100644
--- a/pkg/front_end/testcases/inference_new/static_assign_combiner.dart
+++ b/pkg/front_end/testcases/inference_new/static_assign_combiner.dart
@@ -30,18 +30,19 @@
 void set target(B value) {}
 
 void test1() {
-  target *= /*@ typeArgs=dynamic */ f();
-  var /*@ type=C* */ x = target *= /*@ typeArgs=dynamic */ f();
+  target /*@ target=A::* */ *= /*@ typeArgs=D* */ f();
+  var /*@ type=C* */ x = target /*@ target=A::* */ *= /*@ typeArgs=D* */ f();
 }
 
 void test2() {
-  ++target;
-  var /*@ type=C* */ x = ++target;
+  /*@ target=A::+ */ ++target;
+  var /*@ type=C* */ x = /*@ target=A::+ */ ++target;
 }
 
 void test3() {
-  target++;
-  var /*@ type=A* */ x = target++;
+  target /*@ target=A::+ */ ++;
+  var /*@ type=A* */ x = /*@ type=A* */ target
+      /*@ type=C* */ /*@ target=A::+ */ ++;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.strong.expect b/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.strong.expect
index c941a13..cc0f51e 100644
--- a/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.strong.expect
@@ -46,8 +46,8 @@
   return null;
 static set target(self::B* value) → void {}
 static method test1() → void {
-  self::target = self::target.{self::A::*}(self::f<dynamic>() as{TypeError} self::D*);
-  self::C* x = self::target = self::target.{self::A::*}(self::f<dynamic>() as{TypeError} self::D*);
+  self::target = self::target.{self::A::*}(self::f<self::D*>());
+  self::C* x = self::target = self::target.{self::A::*}(self::f<self::D*>());
 }
 static method test2() → void {
   self::target = self::target.{self::A::+}(1);
diff --git a/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.strong.transformed.expect
index c941a13..cc0f51e 100644
--- a/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.strong.transformed.expect
@@ -46,8 +46,8 @@
   return null;
 static set target(self::B* value) → void {}
 static method test1() → void {
-  self::target = self::target.{self::A::*}(self::f<dynamic>() as{TypeError} self::D*);
-  self::C* x = self::target = self::target.{self::A::*}(self::f<dynamic>() as{TypeError} self::D*);
+  self::target = self::target.{self::A::*}(self::f<self::D*>());
+  self::C* x = self::target = self::target.{self::A::*}(self::f<self::D*>());
 }
 static method test2() → void {
   self::target = self::target.{self::A::+}(1);
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart b/pkg/front_end/testcases/nnbd/function_types.dart
new file mode 100644
index 0000000..67c0108
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/function_types.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.
+
+typedef F = void Function();
+
+void foo() {}
+F bar() => foo;
+F? baz() => foo;
+void Function() hest() => foo;
+void Function()? fisk() => foo;
+
+Function()? foobar(Function()? x) => null;
+
+class A<T> {}
+class B extends A<Function()?> {
+  Function()? method(Function()? x) => null;
+}
+
+main() {
+  void Function() g;
+  void Function()? f = g;
+
+  var fBar = bar();
+  var fBaz = baz();
+  var fHest = hest();
+  var fFisk = fisk();
+}
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.outline.expect b/pkg/front_end/testcases/nnbd/function_types.dart.outline.expect
new file mode 100644
index 0000000..eb8a0fd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.outline.expect
@@ -0,0 +1,29 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F = () → void;
+class A<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T*>*
+    ;
+}
+class B extends self::A<() →? dynamic> {
+  synthetic constructor •() → self::B*
+    ;
+  method method(() →? dynamic x) → () →? dynamic
+    ;
+}
+static method foo() → void
+  ;
+static method bar() → () → void
+  ;
+static method baz() → () → void
+  ;
+static method hest() → () → void
+  ;
+static method fisk() → () →? void
+  ;
+static method foobar(() →? dynamic x) → () →? dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect b/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect
new file mode 100644
index 0000000..a1e7b4a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect
@@ -0,0 +1,40 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F = () → void;
+class A<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T*>*
+    : super core::Object::•()
+    ;
+}
+class B extends self::A<() →? dynamic> {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+  method method(() →? dynamic x) → () →? dynamic
+    return null;
+}
+static method foo() → void {}
+static method bar() → () → void
+  return #C1;
+static method baz() → () → void
+  return #C1;
+static method hest() → () → void
+  return #C1;
+static method fisk() → () →? void
+  return #C1;
+static method foobar(() →? dynamic x) → () →? dynamic
+  return null;
+static method main() → dynamic {
+  () → void g;
+  () →? void f = g;
+  () → void fBar = self::bar();
+  () → void fBaz = self::baz();
+  () → void fHest = self::hest();
+  () →? void fFisk = self::fisk();
+}
+
+constants  {
+  #C1 = tearoff self::foo
+}
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect
new file mode 100644
index 0000000..a1e7b4a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect
@@ -0,0 +1,40 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef F = () → void;
+class A<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T*>*
+    : super core::Object::•()
+    ;
+}
+class B extends self::A<() →? dynamic> {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+  method method(() →? dynamic x) → () →? dynamic
+    return null;
+}
+static method foo() → void {}
+static method bar() → () → void
+  return #C1;
+static method baz() → () → void
+  return #C1;
+static method hest() → () → void
+  return #C1;
+static method fisk() → () →? void
+  return #C1;
+static method foobar(() →? dynamic x) → () →? dynamic
+  return null;
+static method main() → dynamic {
+  () → void g;
+  () →? void f = g;
+  () → void fBar = self::bar();
+  () → void fBaz = self::baz();
+  () → void fHest = self::hest();
+  () →? void fFisk = self::fisk();
+}
+
+constants  {
+  #C1 = tearoff self::foo
+}
diff --git a/pkg/front_end/testcases/nnbd/nullable_param.dart.outline.expect b/pkg/front_end/testcases/nnbd/nullable_param.dart.outline.expect
index 18fe203..a40317e 100644
--- a/pkg/front_end/testcases/nnbd/nullable_param.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_param.dart.outline.expect
@@ -27,5 +27,5 @@
 }
 static method main() → dynamic
   ;
-static method test_nullable_function_type_formal_param({() →* core::int f}) → core::int
+static method test_nullable_function_type_formal_param({() →? core::int f}) → core::int
   ;
diff --git a/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.expect b/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.expect
index 977546a..d0af2e7 100644
--- a/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.expect
@@ -30,9 +30,9 @@
   self::Foo foo = new self::Foo::•();
   foo.{self::Foo::field} = 5;
   foo.{self::Foo::bar}(6);
-  self::test_nullable_function_type_formal_param(f: () → core::int* => 2);
+  self::test_nullable_function_type_formal_param(f: () → core::int => 2);
 }
-static method test_nullable_function_type_formal_param({() →* core::int f = #C1}) → core::int {
+static method test_nullable_function_type_formal_param({() →? core::int f = #C1}) → core::int {
   return let final core::int #t1 = f.call() in #t1.==(null) ?{core::int*} 1.{core::int::unary-}() : #t1;
 }
 
diff --git a/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.transformed.expect
index 977546a..d0af2e7 100644
--- a/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.transformed.expect
@@ -30,9 +30,9 @@
   self::Foo foo = new self::Foo::•();
   foo.{self::Foo::field} = 5;
   foo.{self::Foo::bar}(6);
-  self::test_nullable_function_type_formal_param(f: () → core::int* => 2);
+  self::test_nullable_function_type_formal_param(f: () → core::int => 2);
 }
-static method test_nullable_function_type_formal_param({() →* core::int f = #C1}) → core::int {
+static method test_nullable_function_type_formal_param({() →? core::int f = #C1}) → core::int {
   return let final core::int #t1 = f.call() in #t1.==(null) ?{core::int*} 1.{core::int::unary-}() : #t1;
 }
 
diff --git a/pkg/front_end/testcases/nnbd/required.dart.outline.expect b/pkg/front_end/testcases/nnbd/required.dart.outline.expect
index 044b885..d5dda81 100644
--- a/pkg/front_end/testcases/nnbd/required.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/required.dart.outline.expect
@@ -2,15 +2,15 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Typedef1 = ({a: core::int, required b: core::int}) →* dynamic;
-typedef Typedef2 = ({a: core::int, required b: core::int}) →* dynamic;
+typedef Typedef1 = ({a: core::int, required b: core::int}) → dynamic;
+typedef Typedef2 = ({a: core::int, required b: core::int}) → dynamic;
 class Class extends core::Object {
   synthetic constructor •() → self::Class*
     ;
   method method({core::int a, required core::int b, required final core::int c, required covariant final core::int d}) → dynamic
     ;
 }
-static field ({a: core::int, required b: core::int}) →* dynamic field;
+static field ({a: core::int, required b: core::int}) → dynamic field;
 static method method({core::int a, required core::int b, required final core::int c}) → dynamic
   ;
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/nnbd/required.dart.strong.expect b/pkg/front_end/testcases/nnbd/required.dart.strong.expect
index a23a59d..4ce5b20 100644
--- a/pkg/front_end/testcases/nnbd/required.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/required.dart.strong.expect
@@ -2,15 +2,15 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Typedef1 = ({a: core::int, required b: core::int}) →* dynamic;
-typedef Typedef2 = ({a: core::int, required b: core::int}) →* dynamic;
+typedef Typedef1 = ({a: core::int, required b: core::int}) → dynamic;
+typedef Typedef2 = ({a: core::int, required b: core::int}) → dynamic;
 class Class extends core::Object {
   synthetic constructor •() → self::Class*
     : super core::Object::•()
     ;
   method method({core::int a = #C1, required core::int b = #C1, required final core::int c = #C1, required covariant final core::int d = #C1}) → dynamic {}
 }
-static field ({a: core::int, required b: core::int}) →* dynamic field;
+static field ({a: core::int, required b: core::int}) → dynamic field;
 static method method({core::int a = #C1, required core::int b = #C1, required final core::int c = #C1}) → dynamic {}
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/required.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/required.dart.strong.transformed.expect
index a23a59d..4ce5b20 100644
--- a/pkg/front_end/testcases/nnbd/required.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/required.dart.strong.transformed.expect
@@ -2,15 +2,15 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Typedef1 = ({a: core::int, required b: core::int}) →* dynamic;
-typedef Typedef2 = ({a: core::int, required b: core::int}) →* dynamic;
+typedef Typedef1 = ({a: core::int, required b: core::int}) → dynamic;
+typedef Typedef2 = ({a: core::int, required b: core::int}) → dynamic;
 class Class extends core::Object {
   synthetic constructor •() → self::Class*
     : super core::Object::•()
     ;
   method method({core::int a = #C1, required core::int b = #C1, required final core::int c = #C1, required covariant final core::int d = #C1}) → dynamic {}
 }
-static field ({a: core::int, required b: core::int}) →* dynamic field;
+static field ({a: core::int, required b: core::int}) → dynamic field;
 static method method({core::int a = #C1, required core::int b = #C1, required final core::int c = #C1}) → dynamic {}
 static method main() → dynamic {}
 
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
new file mode 100644
index 0000000..ce5e225
--- /dev/null
+++ b/pkg/front_end/testcases/old_dills/dart2js.version.32.compile.1.dill
Binary files differ
diff --git a/pkg/front_end/testcases/rasta/generic_factory.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/generic_factory.dart.strong.transformed.expect
index c8ebf36..d362a24 100644
--- a/pkg/front_end/testcases/rasta/generic_factory.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/generic_factory.dart.strong.transformed.expect
@@ -52,9 +52,9 @@
     : super core::Object::•()
     ;
   static factory a<T extends core::Object* = dynamic>() → self::A<self::A::a::T*>*
-    let <S extends core::Object* = dynamic>() →* self::B<self::B::a::S*>* #redirecting_factory = self::B::a in let self::A::a::T* #typeArg0 = null in invalid-expression;
+    let <S extends core::Object* = dynamic>() →* self::B<S*>* #redirecting_factory = self::B::a in let self::A::a::T* #typeArg0 = null in invalid-expression;
   static factory b<T extends core::Object* = dynamic>() → self::A<self::A::b::T*>*
-    let <S extends core::Object* = dynamic>() →* self::B<self::B::a::S*>* #redirecting_factory = self::B::a in let self::C1* #typeArg0 = null in invalid-expression;
+    let <S extends core::Object* = dynamic>() →* self::B<S*>* #redirecting_factory = self::B::a in let self::C1* #typeArg0 = null in invalid-expression;
   static factory c<T extends core::Object* = dynamic>() → self::A<self::A::c::T*>*
     let core::String* #redirecting_factory = "Missing" in invalid-expression;
 }
diff --git a/pkg/front_end/testcases/rasta/issue_000052.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000052.dart.strong.expect
index ed31e8d..2130845 100644
--- a/pkg/front_end/testcases/rasta/issue_000052.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000052.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 static method main() → dynamic {
-  function f() → core::Null* {
+  function f() → core::Null? {
     core::print("hello");
   }
   f.call();
diff --git a/pkg/front_end/testcases/rasta/issue_000052.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000052.dart.strong.transformed.expect
index ed31e8d..2130845 100644
--- a/pkg/front_end/testcases/rasta/issue_000052.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000052.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 static method main() → dynamic {
-  function f() → core::Null* {
+  function f() → core::Null? {
     core::print("hello");
   }
   f.call();
diff --git a/pkg/front_end/testcases/rasta/issue_000070.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000070.dart.outline.expect
index afa2636..c7a0e81 100644
--- a/pkg/front_end/testcases/rasta/issue_000070.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000070.dart.outline.expect
@@ -11,7 +11,7 @@
   constructor empty() → self::A<self::A::N*, self::A::S*, self::A::U*>*
     ;
   const constructor c(self::A::U* u, self::A::S* s) → self::A<self::A::N*, self::A::S*, self::A::U*>*
-    : self::A::field = const <core::Null*>[null], super core::Object::•()
+    : self::A::field = const <core::Null?>[null], super core::Object::•()
     ;
   static factory f<N extends core::Object* = dynamic, S extends core::Object* = dynamic, U extends core::Object* = dynamic>(self::A::f::S* s) → self::A<self::A::f::N*, self::A::f::S*, self::A::f::U*>*
     ;
diff --git a/pkg/front_end/testcases/rasta/issue_000070.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000070.dart.strong.expect
index c9aa9ff..8718610 100644
--- a/pkg/front_end/testcases/rasta/issue_000070.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000070.dart.strong.expect
@@ -46,6 +46,6 @@
 
 constants  {
   #C1 = null
-  #C2 = <core::Null*>[#C1]
+  #C2 = <core::Null?>[#C1]
   #C3 = self::A<core::int*, core::int*, core::List<dynamic>*> {field:#C2}
 }
diff --git a/pkg/front_end/testcases/rasta/issue_000070.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000070.dart.strong.transformed.expect
index 9a4571e..e5097ea 100644
--- a/pkg/front_end/testcases/rasta/issue_000070.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000070.dart.strong.transformed.expect
@@ -46,6 +46,6 @@
 
 constants  {
   #C1 = null
-  #C2 = <core::Null*>[#C1]
+  #C2 = <core::Null?>[#C1]
   #C3 = self::A<core::int*, core::int*, core::List<dynamic>*> {field:#C2}
 }
diff --git a/pkg/front_end/testcases/rasta/issue_000081.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000081.dart.strong.expect
index 17c277f..ecdd7b2 100644
--- a/pkg/front_end/testcases/rasta/issue_000081.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000081.dart.strong.expect
@@ -21,6 +21,6 @@
 }
 static method main() → dynamic {
   core::print(new self::Sub::•().{self::Sub::hashCode});
-  core::List<core::Null*>* l = <core::Null*>[null];
-  let final core::List<core::Null*>* #t2 = l in let final core::int* #t3 = 0 in #t2.{core::List::[]}(#t3).{core::Object::==}(null) ?{core::String*} let final core::String* #t4 = "fisk" as{TypeError} core::Null* in let final void #t5 = #t2.{core::List::[]=}(#t3, #t4) in #t4 : null;
+  core::List<core::Null?>* l = <core::Null?>[null];
+  let final core::List<core::Null?>* #t2 = l in let final core::int* #t3 = 0 in #t2.{core::List::[]}(#t3).{core::Object::==}(null) ?{core::String*} #t2.{core::List::[]=}(#t3, "fisk" as{TypeError} core::Null?) : null;
 }
diff --git a/pkg/front_end/testcases/rasta/issue_000081.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000081.dart.strong.transformed.expect
index 17c277f..ecdd7b2 100644
--- a/pkg/front_end/testcases/rasta/issue_000081.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000081.dart.strong.transformed.expect
@@ -21,6 +21,6 @@
 }
 static method main() → dynamic {
   core::print(new self::Sub::•().{self::Sub::hashCode});
-  core::List<core::Null*>* l = <core::Null*>[null];
-  let final core::List<core::Null*>* #t2 = l in let final core::int* #t3 = 0 in #t2.{core::List::[]}(#t3).{core::Object::==}(null) ?{core::String*} let final core::String* #t4 = "fisk" as{TypeError} core::Null* in let final void #t5 = #t2.{core::List::[]=}(#t3, #t4) in #t4 : null;
+  core::List<core::Null?>* l = <core::Null?>[null];
+  let final core::List<core::Null?>* #t2 = l in let final core::int* #t3 = 0 in #t2.{core::List::[]}(#t3).{core::Object::==}(null) ?{core::String*} #t2.{core::List::[]=}(#t3, "fisk" as{TypeError} core::Null?) : null;
 }
diff --git a/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.expect b/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.expect
index 391c477..9096c74 100644
--- a/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.expect
@@ -20,6 +20,11 @@
 // main(arguments = [x]) {
 //                ^
 //
+// pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart:5:18: Error: Constant expression expected.
+// Try inserting 'const'.
+// main(arguments = [x]) {
+//                  ^
+//
 // pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart:5:19: Error: Getter not found: 'x'.
 // main(arguments = [x]) {
 //                   ^
diff --git a/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.transformed.expect
index 391c477..9096c74 100644
--- a/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart.strong.transformed.expect
@@ -20,6 +20,11 @@
 // main(arguments = [x]) {
 //                ^
 //
+// pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart:5:18: Error: Constant expression expected.
+// Try inserting 'const'.
+// main(arguments = [x]) {
+//                  ^
+//
 // pkg/front_end/testcases/rasta/mandatory_parameter_initializer.dart:5:19: Error: Getter not found: 'x'.
 // main(arguments = [x]) {
 //                   ^
diff --git a/pkg/front_end/testcases/rasta/static.dart.strong.expect b/pkg/front_end/testcases/rasta/static.dart.strong.expect
index 30a8714..2cee8d5 100644
--- a/pkg/front_end/testcases/rasta/static.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/static.dart.strong.expect
@@ -138,26 +138,6 @@
 //     use(Foo.staticSetter ??= 87);
 //             ^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/rasta/static.dart:35:23: Error: The method '+' isn't defined for the class 'dynamic Function()'.
-// Try correcting the name to the name of an existing method, or defining a method named '+'.
-//     Foo.staticFunction++;
-//                       ^
-//
-// pkg/front_end/testcases/rasta/static.dart:36:27: Error: The method '+' isn't defined for the class 'dynamic Function()'.
-// Try correcting the name to the name of an existing method, or defining a method named '+'.
-//     use(Foo.staticFunction++);
-//                           ^
-//
-// pkg/front_end/testcases/rasta/static.dart:46:5: Error: The method '+' isn't defined for the class 'dynamic Function()'.
-// Try correcting the name to the name of an existing method, or defining a method named '+'.
-//     ++Foo.staticFunction;
-//     ^
-//
-// pkg/front_end/testcases/rasta/static.dart:47:9: Error: The method '+' isn't defined for the class 'dynamic Function()'.
-// Try correcting the name to the name of an existing method, or defining a method named '+'.
-//     use(++Foo.staticFunction);
-//         ^
-//
 // pkg/front_end/testcases/rasta/static.dart:53:23: Error: The method 'call' isn't defined for the class 'int'.
 // Try correcting the name to the name of an existing method, or defining a method named 'call'.
 //     Foo.staticConstant();
@@ -215,7 +195,7 @@
     invalid-expression "pkg/front_end/testcases/rasta/static.dart:31:9: Error: Setter not found: 'staticConstant'.
     Foo.staticConstant++;
         ^^^^^^^^^^^^^^";
-    self::use(let final core::int* #t1 = #C1 in let final core::int* #t2 = invalid-expression "pkg/front_end/testcases/rasta/static.dart:32:13: Error: Setter not found: 'staticConstant'.
+    self::use(let final core::int* #t1 = #C1 in let final dynamic #t2 = invalid-expression "pkg/front_end/testcases/rasta/static.dart:32:13: Error: Setter not found: 'staticConstant'.
     use(Foo.staticConstant++);
             ^^^^^^^^^^^^^^" in #t1);
     self::Foo::staticField = self::Foo::staticField.{core::num::+}(1);
@@ -312,18 +292,18 @@
             ^^^^^^^^^^^^");
     self::Foo::staticSetter = 87;
     self::use(self::Foo::staticSetter = 87);
-    (#C1).{core::Object::==}(null) ?{core::int*} invalid-expression "pkg/front_end/testcases/rasta/static.dart:75:9: Error: Setter not found: 'staticConstant'.
+    (#C1).{core::num::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/static.dart:75:9: Error: Setter not found: 'staticConstant'.
     Foo.staticConstant ??= 87;
         ^^^^^^^^^^^^^^" : null;
-    self::use(let final core::int* #t11 = #C1 in #t11.{core::Object::==}(null) ?{core::int*} invalid-expression "pkg/front_end/testcases/rasta/static.dart:76:13: Error: Setter not found: 'staticConstant'.
+    self::use(let final core::int* #t11 = #C1 in #t11.{core::num::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/static.dart:76:13: Error: Setter not found: 'staticConstant'.
     use(Foo.staticConstant ??= 87);
             ^^^^^^^^^^^^^^" : #t11);
     self::Foo::staticField.{core::num::==}(null) ?{core::int*} self::Foo::staticField = 87 : null;
     self::use(let final core::int* #t12 = self::Foo::staticField in #t12.{core::num::==}(null) ?{core::int*} self::Foo::staticField = 87 : #t12);
-    (#C2).{core::Object::==}(null) ?{core::Object*} invalid-expression "pkg/front_end/testcases/rasta/static.dart:79:9: Error: Setter not found: 'staticFunction'.
+    (#C2).{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/static.dart:79:9: Error: Setter not found: 'staticFunction'.
     Foo.staticFunction ??= 87;
         ^^^^^^^^^^^^^^" : null;
-    self::use(let final () →* dynamic #t13 = #C2 in #t13.{core::Object::==}(null) ?{core::Object*} invalid-expression "pkg/front_end/testcases/rasta/static.dart:80:13: Error: Setter not found: 'staticFunction'.
+    self::use(let final () →* dynamic #t13 = #C2 in #t13.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/static.dart:80:13: Error: Setter not found: 'staticFunction'.
     use(Foo.staticFunction ??= 87);
             ^^^^^^^^^^^^^^" : #t13);
     self::Foo::staticGetter.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/static.dart:81:9: Error: Setter not found: 'staticGetter'.
diff --git a/pkg/front_end/testcases/rasta/static.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/static.dart.strong.transformed.expect
index 30a8714..2cee8d5 100644
--- a/pkg/front_end/testcases/rasta/static.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/static.dart.strong.transformed.expect
@@ -138,26 +138,6 @@
 //     use(Foo.staticSetter ??= 87);
 //             ^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/rasta/static.dart:35:23: Error: The method '+' isn't defined for the class 'dynamic Function()'.
-// Try correcting the name to the name of an existing method, or defining a method named '+'.
-//     Foo.staticFunction++;
-//                       ^
-//
-// pkg/front_end/testcases/rasta/static.dart:36:27: Error: The method '+' isn't defined for the class 'dynamic Function()'.
-// Try correcting the name to the name of an existing method, or defining a method named '+'.
-//     use(Foo.staticFunction++);
-//                           ^
-//
-// pkg/front_end/testcases/rasta/static.dart:46:5: Error: The method '+' isn't defined for the class 'dynamic Function()'.
-// Try correcting the name to the name of an existing method, or defining a method named '+'.
-//     ++Foo.staticFunction;
-//     ^
-//
-// pkg/front_end/testcases/rasta/static.dart:47:9: Error: The method '+' isn't defined for the class 'dynamic Function()'.
-// Try correcting the name to the name of an existing method, or defining a method named '+'.
-//     use(++Foo.staticFunction);
-//         ^
-//
 // pkg/front_end/testcases/rasta/static.dart:53:23: Error: The method 'call' isn't defined for the class 'int'.
 // Try correcting the name to the name of an existing method, or defining a method named 'call'.
 //     Foo.staticConstant();
@@ -215,7 +195,7 @@
     invalid-expression "pkg/front_end/testcases/rasta/static.dart:31:9: Error: Setter not found: 'staticConstant'.
     Foo.staticConstant++;
         ^^^^^^^^^^^^^^";
-    self::use(let final core::int* #t1 = #C1 in let final core::int* #t2 = invalid-expression "pkg/front_end/testcases/rasta/static.dart:32:13: Error: Setter not found: 'staticConstant'.
+    self::use(let final core::int* #t1 = #C1 in let final dynamic #t2 = invalid-expression "pkg/front_end/testcases/rasta/static.dart:32:13: Error: Setter not found: 'staticConstant'.
     use(Foo.staticConstant++);
             ^^^^^^^^^^^^^^" in #t1);
     self::Foo::staticField = self::Foo::staticField.{core::num::+}(1);
@@ -312,18 +292,18 @@
             ^^^^^^^^^^^^");
     self::Foo::staticSetter = 87;
     self::use(self::Foo::staticSetter = 87);
-    (#C1).{core::Object::==}(null) ?{core::int*} invalid-expression "pkg/front_end/testcases/rasta/static.dart:75:9: Error: Setter not found: 'staticConstant'.
+    (#C1).{core::num::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/static.dart:75:9: Error: Setter not found: 'staticConstant'.
     Foo.staticConstant ??= 87;
         ^^^^^^^^^^^^^^" : null;
-    self::use(let final core::int* #t11 = #C1 in #t11.{core::Object::==}(null) ?{core::int*} invalid-expression "pkg/front_end/testcases/rasta/static.dart:76:13: Error: Setter not found: 'staticConstant'.
+    self::use(let final core::int* #t11 = #C1 in #t11.{core::num::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/static.dart:76:13: Error: Setter not found: 'staticConstant'.
     use(Foo.staticConstant ??= 87);
             ^^^^^^^^^^^^^^" : #t11);
     self::Foo::staticField.{core::num::==}(null) ?{core::int*} self::Foo::staticField = 87 : null;
     self::use(let final core::int* #t12 = self::Foo::staticField in #t12.{core::num::==}(null) ?{core::int*} self::Foo::staticField = 87 : #t12);
-    (#C2).{core::Object::==}(null) ?{core::Object*} invalid-expression "pkg/front_end/testcases/rasta/static.dart:79:9: Error: Setter not found: 'staticFunction'.
+    (#C2).{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/static.dart:79:9: Error: Setter not found: 'staticFunction'.
     Foo.staticFunction ??= 87;
         ^^^^^^^^^^^^^^" : null;
-    self::use(let final () →* dynamic #t13 = #C2 in #t13.{core::Object::==}(null) ?{core::Object*} invalid-expression "pkg/front_end/testcases/rasta/static.dart:80:13: Error: Setter not found: 'staticFunction'.
+    self::use(let final () →* dynamic #t13 = #C2 in #t13.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/static.dart:80:13: Error: Setter not found: 'staticFunction'.
     use(Foo.staticFunction ??= 87);
             ^^^^^^^^^^^^^^" : #t13);
     self::Foo::staticGetter.{core::Object::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/static.dart:81:9: Error: Setter not found: 'staticGetter'.
diff --git a/pkg/front_end/testcases/regress/issue_29937.dart.strong.expect b/pkg/front_end/testcases/regress/issue_29937.dart.strong.expect
index 976b248..c6c6d4d 100644
--- a/pkg/front_end/testcases/regress/issue_29937.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_29937.dart.strong.expect
@@ -10,5 +10,5 @@
 import "dart:core" as core;
 
 static method main() → dynamic {
-  <() →* core::Null*>[let final () →* core::Null* f = () → core::Null* {} in f];
+  <() →* core::Null?>[let final () →* core::Null? f = () → core::Null? {} in f];
 }
diff --git a/pkg/front_end/testcases/regress/issue_29937.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_29937.dart.strong.transformed.expect
index 976b248..c6c6d4d 100644
--- a/pkg/front_end/testcases/regress/issue_29937.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_29937.dart.strong.transformed.expect
@@ -10,5 +10,5 @@
 import "dart:core" as core;
 
 static method main() → dynamic {
-  <() →* core::Null*>[let final () →* core::Null* f = () → core::Null* {} in f];
+  <() →* core::Null?>[let final () →* core::Null? f = () → core::Null? {} in f];
 }
diff --git a/pkg/front_end/testcases/regress/issue_29942.dart.strong.expect b/pkg/front_end/testcases/regress/issue_29942.dart.strong.expect
index de81539..a052ac0 100644
--- a/pkg/front_end/testcases/regress/issue_29942.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_29942.dart.strong.expect
@@ -16,4 +16,4 @@
 
 static method main() → dynamic {}
 static method f() → dynamic
-  return let final () →* core::Null* h = () → core::Null* => null in h;
+  return let final () →* core::Null? h = () → core::Null? => null in h;
diff --git a/pkg/front_end/testcases/regress/issue_29942.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_29942.dart.strong.transformed.expect
index de81539..a052ac0 100644
--- a/pkg/front_end/testcases/regress/issue_29942.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_29942.dart.strong.transformed.expect
@@ -16,4 +16,4 @@
 
 static method main() → dynamic {}
 static method f() → dynamic
-  return let final () →* core::Null* h = () → core::Null* => null in h;
+  return let final () →* core::Null? h = () → core::Null? => null in h;
diff --git a/pkg/front_end/testcases/regress/issue_29978.dart.strong.expect b/pkg/front_end/testcases/regress/issue_29978.dart.strong.expect
index 01dbc9a..86dc966 100644
--- a/pkg/front_end/testcases/regress/issue_29978.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_29978.dart.strong.expect
@@ -12,5 +12,5 @@
 static method foo(dynamic a, dynamic b) → dynamic
   return null;
 static method main() → dynamic {
-  self::foo(null, let final () →* core::Null* f = () → core::Null* {} in f);
+  self::foo(null, let final () →* core::Null? f = () → core::Null? {} in f);
 }
diff --git a/pkg/front_end/testcases/regress/issue_29978.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_29978.dart.strong.transformed.expect
index 01dbc9a..86dc966 100644
--- a/pkg/front_end/testcases/regress/issue_29978.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_29978.dart.strong.transformed.expect
@@ -12,5 +12,5 @@
 static method foo(dynamic a, dynamic b) → dynamic
   return null;
 static method main() → dynamic {
-  self::foo(null, let final () →* core::Null* f = () → core::Null* {} in f);
+  self::foo(null, let final () →* core::Null? f = () → core::Null? {} in f);
 }
diff --git a/pkg/front_end/testcases/regress/issue_29979.dart.strong.expect b/pkg/front_end/testcases/regress/issue_29979.dart.strong.expect
index cdc5774..df04eff 100644
--- a/pkg/front_end/testcases/regress/issue_29979.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_29979.dart.strong.expect
@@ -10,5 +10,5 @@
 import "dart:core" as core;
 
 static method main() → dynamic {
-  (let final () →* core::Null* f = () → core::Null* {} in f).call();
+  (let final () →* core::Null? f = () → core::Null? {} in f).call();
 }
diff --git a/pkg/front_end/testcases/regress/issue_29979.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_29979.dart.strong.transformed.expect
index cdc5774..df04eff 100644
--- a/pkg/front_end/testcases/regress/issue_29979.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_29979.dart.strong.transformed.expect
@@ -10,5 +10,5 @@
 import "dart:core" as core;
 
 static method main() → dynamic {
-  (let final () →* core::Null* f = () → core::Null* {} in f).call();
+  (let final () →* core::Null? f = () → core::Null? {} in f).call();
 }
diff --git a/pkg/front_end/testcases/regress/issue_31766.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31766.dart.strong.expect
index cf83ecf..fb78ee0 100644
--- a/pkg/front_end/testcases/regress/issue_31766.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31766.dart.strong.expect
@@ -14,7 +14,7 @@
     core::print("t.foo()=${t.{self::A::foo}()}");
   }
   bar.call<self::A*>(new self::A::•());
-  (<S extends self::A* = self::A*>(S* s) → core::Null* {
+  (<S extends self::A* = self::A*>(S* s) → core::Null? {
     core::print("s.foo()=${s.{self::A::foo}()}");
   }).call<self::A*>(new self::A::•());
 }
diff --git a/pkg/front_end/testcases/regress/issue_31766.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31766.dart.strong.transformed.expect
index cf83ecf..fb78ee0 100644
--- a/pkg/front_end/testcases/regress/issue_31766.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31766.dart.strong.transformed.expect
@@ -14,7 +14,7 @@
     core::print("t.foo()=${t.{self::A::foo}()}");
   }
   bar.call<self::A*>(new self::A::•());
-  (<S extends self::A* = self::A*>(S* s) → core::Null* {
+  (<S extends self::A* = self::A*>(S* s) → core::Null? {
     core::print("s.foo()=${s.{self::A::foo}()}");
   }).call<self::A*>(new self::A::•());
 }
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.strong.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.strong.expect
index 1f1240e..ce550cf 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.strong.expect
@@ -10,7 +10,7 @@
   method f<U extends (self::C::T*) →* void = (self::C::T*) →* void>(self::C::f::U* x) → void {}
 }
 static method g(self::C<core::num*>* c) → void {
-  c.{self::C::f}<(core::Object*) →* void>((core::Object* o) → core::Null* {});
+  c.{self::C::f}<(core::Object*) →* void>((core::Object* o) → core::Null? {});
 }
 static method test() → void {
   self::g(new self::C::•<core::int*>());
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.strong.transformed.expect
index 1f1240e..ce550cf 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_method_type_parameter.dart.strong.transformed.expect
@@ -10,7 +10,7 @@
   method f<U extends (self::C::T*) →* void = (self::C::T*) →* void>(self::C::f::U* x) → void {}
 }
 static method g(self::C<core::num*>* c) → void {
-  c.{self::C::f}<(core::Object*) →* void>((core::Object* o) → core::Null* {});
+  c.{self::C::f}<(core::Object*) →* void>((core::Object* o) → core::Null? {});
 }
 static method test() → void {
   self::g(new self::C::•<core::int*>());
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.strong.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.strong.expect
index dd9a3f3..77140dc 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.strong.expect
@@ -13,15 +13,15 @@
   }
 }
 static method g1(self::C<core::num*>* c) → void {
-  (core::num*) →* void x = let final self::C<core::num*>* #t1 = c in #t1.==(null) ?{(core::num*) →* void} null : #t1.{self::C::f1}() as{TypeError} (core::num*) →* void;
+  (core::num*) →* void x = let final self::C<core::num*>* #t1 = c in #t1.{core::Object::==}(null) ?{(core::num*) →* void} null : #t1.{self::C::f1}() as{TypeError} (core::num*) →* void;
   core::print("hello");
   x.call(1.5);
 }
 static method g2(self::C<core::num*>* c) → void {
-  (core::int*) →* void x = let final self::C<core::num*>* #t2 = c in #t2.==(null) ?{(core::num*) →* void} null : #t2.{self::C::f1}() as{TypeError} (core::num*) →* void;
+  (core::int*) →* void x = let final self::C<core::num*>* #t2 = c in #t2.{core::Object::==}(null) ?{(core::num*) →* void} null : #t2.{self::C::f1}() as{TypeError} (core::num*) →* void;
   x.call(1);
 }
 static method g3(self::C<core::num*>* c) → void {
-  core::List<(core::num*) →* void>* x = let final self::C<core::num*>* #t3 = c in #t3.==(null) ?{core::List<(core::num*) →* void>*} null : #t3.{self::C::f2}() as{TypeError} core::List<(core::num*) →* void>*;
+  core::List<(core::num*) →* void>* x = let final self::C<core::num*>* #t3 = c in #t3.{core::Object::==}(null) ?{core::List<(core::num*) →* void>*} null : #t3.{self::C::f2}() as{TypeError} core::List<(core::num*) →* void>*;
 }
 static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.strong.transformed.expect
index dd9a3f3..77140dc 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.strong.transformed.expect
@@ -13,15 +13,15 @@
   }
 }
 static method g1(self::C<core::num*>* c) → void {
-  (core::num*) →* void x = let final self::C<core::num*>* #t1 = c in #t1.==(null) ?{(core::num*) →* void} null : #t1.{self::C::f1}() as{TypeError} (core::num*) →* void;
+  (core::num*) →* void x = let final self::C<core::num*>* #t1 = c in #t1.{core::Object::==}(null) ?{(core::num*) →* void} null : #t1.{self::C::f1}() as{TypeError} (core::num*) →* void;
   core::print("hello");
   x.call(1.5);
 }
 static method g2(self::C<core::num*>* c) → void {
-  (core::int*) →* void x = let final self::C<core::num*>* #t2 = c in #t2.==(null) ?{(core::num*) →* void} null : #t2.{self::C::f1}() as{TypeError} (core::num*) →* void;
+  (core::int*) →* void x = let final self::C<core::num*>* #t2 = c in #t2.{core::Object::==}(null) ?{(core::num*) →* void} null : #t2.{self::C::f1}() as{TypeError} (core::num*) →* void;
   x.call(1);
 }
 static method g3(self::C<core::num*>* c) → void {
-  core::List<(core::num*) →* void>* x = let final self::C<core::num*>* #t3 = c in #t3.==(null) ?{core::List<(core::num*) →* void>*} null : #t3.{self::C::f2}() as{TypeError} core::List<(core::num*) →* void>*;
+  core::List<(core::num*) →* void>* x = let final self::C<core::num*>* #t3 = c in #t3.{core::Object::==}(null) ?{core::List<(core::num*) →* void>*} null : #t3.{self::C::f2}() as{TypeError} core::List<(core::num*) →* void>*;
 }
 static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.strong.expect b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.strong.expect
index c4f2438..b534829 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.strong.expect
@@ -14,15 +14,15 @@
   }
 }
 static method g1(self::C<core::num*>* c) → void {
-  (core::num*) →* void x = let final self::C<core::num*>* #t1 = c in #t1.==(null) ?{(core::num*) →* void} null : #t1.{self::C::f1} as{TypeError} (core::num*) →* void;
+  (core::num*) →* void x = let final self::C<core::num*>* #t1 = c in #t1.{core::Object::==}(null) ?{(core::num*) →* void} null : #t1.{self::C::f1} as{TypeError} (core::num*) →* void;
   core::print("hello");
   x.call(1.5);
 }
 static method g2(self::C<core::num*>* c) → void {
-  (core::int*) →* void x = let final self::C<core::num*>* #t2 = c in #t2.==(null) ?{(core::num*) →* void} null : #t2.{self::C::f1} as{TypeError} (core::num*) →* void;
+  (core::int*) →* void x = let final self::C<core::num*>* #t2 = c in #t2.{core::Object::==}(null) ?{(core::num*) →* void} null : #t2.{self::C::f1} as{TypeError} (core::num*) →* void;
   x.call(1);
 }
 static method g3(self::C<core::num*>* c) → void {
-  core::List<(core::num*) →* void>* x = let final self::C<core::num*>* #t3 = c in #t3.==(null) ?{core::List<(core::num*) →* void>*} null : #t3.{self::C::f2} as{TypeError} core::List<(core::num*) →* void>*;
+  core::List<(core::num*) →* void>* x = let final self::C<core::num*>* #t3 = c in #t3.{core::Object::==}(null) ?{core::List<(core::num*) →* void>*} null : #t3.{self::C::f2} as{TypeError} core::List<(core::num*) →* void>*;
 }
 static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.strong.transformed.expect
index c4f2438..b534829 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.strong.transformed.expect
@@ -14,15 +14,15 @@
   }
 }
 static method g1(self::C<core::num*>* c) → void {
-  (core::num*) →* void x = let final self::C<core::num*>* #t1 = c in #t1.==(null) ?{(core::num*) →* void} null : #t1.{self::C::f1} as{TypeError} (core::num*) →* void;
+  (core::num*) →* void x = let final self::C<core::num*>* #t1 = c in #t1.{core::Object::==}(null) ?{(core::num*) →* void} null : #t1.{self::C::f1} as{TypeError} (core::num*) →* void;
   core::print("hello");
   x.call(1.5);
 }
 static method g2(self::C<core::num*>* c) → void {
-  (core::int*) →* void x = let final self::C<core::num*>* #t2 = c in #t2.==(null) ?{(core::num*) →* void} null : #t2.{self::C::f1} as{TypeError} (core::num*) →* void;
+  (core::int*) →* void x = let final self::C<core::num*>* #t2 = c in #t2.{core::Object::==}(null) ?{(core::num*) →* void} null : #t2.{self::C::f1} as{TypeError} (core::num*) →* void;
   x.call(1);
 }
 static method g3(self::C<core::num*>* c) → void {
-  core::List<(core::num*) →* void>* x = let final self::C<core::num*>* #t3 = c in #t3.==(null) ?{core::List<(core::num*) →* void>*} null : #t3.{self::C::f2} as{TypeError} core::List<(core::num*) →* void>*;
+  core::List<(core::num*) →* void>* x = let final self::C<core::num*>* #t3 = c in #t3.{core::Object::==}(null) ?{core::List<(core::num*) →* void>*} null : #t3.{self::C::f2} as{TypeError} core::List<(core::num*) →* void>*;
 }
 static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.strong.expect
index 6c00c8a..8d3508c 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.strong.expect
@@ -60,7 +60,7 @@
                                              ^" in (#t1.{self::D::value}.{self::C::+}(1) as{TypeError} (core::num*) →* core::num*) as{TypeError} (core::int*) →* core::int*;
   self::expect(d.{self::D::setValue}(0), 1);
   d = new self::D::•(new self::C::•<core::num*>(#C2));
-  self::expectTypeError(() → core::Null* {
+  self::expectTypeError(() → core::Null? {
     let final self::D* #t3 = d in #t3.{self::D::value} = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart:53:48: Error: A value of type 'num Function(num)' can't be assigned to a variable of type 'int Function(int)'.
 Try changing the type of the left hand side, or casting the right hand side to 'int Function(int)'.
     d.value /*@ checkReturn=(num*) ->* num* */ += 1;
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.strong.transformed.expect
index 6c00c8a..8d3508c 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.strong.transformed.expect
@@ -60,7 +60,7 @@
                                              ^" in (#t1.{self::D::value}.{self::C::+}(1) as{TypeError} (core::num*) →* core::num*) as{TypeError} (core::int*) →* core::int*;
   self::expect(d.{self::D::setValue}(0), 1);
   d = new self::D::•(new self::C::•<core::num*>(#C2));
-  self::expectTypeError(() → core::Null* {
+  self::expectTypeError(() → core::Null? {
     let final self::D* #t3 = d in #t3.{self::D::value} = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart:53:48: Error: A value of type 'num Function(num)' can't be assigned to a variable of type 'int Function(int)'.
 Try changing the type of the left hand side, or casting the right hand side to 'int Function(int)'.
     d.value /*@ checkReturn=(num*) ->* num* */ += 1;
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 09538b1..4a65ddd 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,15 +2,15 @@
 //
 // Problems in library:
 //
-// 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)>'.
+// 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)>'.
 //  - 'B' is from 'pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart'.
-// Try changing the type of the left hand side, or casting the right hand side to 'B<void Function(num)>'.
+// Try changing the type of the parameter, or casting the argument to 'B<void Function(num)>'.
 //   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: A value of type 'B<num>' can't be assigned to a variable of type 'B<void Function(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)>'.
 //  - 'B' is from 'pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart'.
-// Try changing the type of the left hand side, or casting the right hand side to 'B<void Function(num)>'.
+// Try changing the type of the parameter, or casting the argument to 'B<void Function(num)>'.
 //   var y = c. /*@ checkReturn=B<(num*) ->* void>* */ x += new B<num>();
 //                                                              ^
 //
@@ -46,14 +46,14 @@
   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: A value of type 'B<num>' can't be assigned to a variable of 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: The argument type 'B<num>' can't be assigned to the parameter type 'B<void Function(num)>'.
  - 'B' is from 'pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart'.
-Try changing the type of the left hand side, or casting the right hand side to 'B<void Function(num)>'.
+Try changing the type of the parameter, or casting the argument to 'B<void Function(num)>'.
   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: A value of type 'B<num>' can't be assigned to a variable of 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: The argument type 'B<num>' can't be assigned to the parameter type 'B<void Function(num)>'.
  - 'B' is from 'pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart'.
-Try changing the type of the left hand side, or casting the right hand side to 'B<void Function(num)>'.
+Try changing the type of the parameter, or casting the argument to 'B<void Function(num)>'.
   var y = c. /*@ checkReturn=B<(num*) ->* void>* */ x += new B<num>();
                                                              ^" in new self::B::•<core::num*>() as{TypeError} self::B<(core::num*) →* void>*);
   let final self::C<core::num*>* #t5 = c in (#t5.{self::C::x} as{TypeError} self::B<(core::num*) →* void>*).{core::Object::==}(null) ?{self::B<core::Object*>*} #t5.{self::C::x} = let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:22:55: Error: A value of type 'B<num>' can't be assigned to a variable of type 'B<void Function(num)>'.
@@ -61,7 +61,7 @@
 Try changing the type of the left hand side, or casting the right hand side to 'B<void Function(num)>'.
   c. /*@ checkReturn=B<(num*) ->* void>* */ x ??= new B<num>();
                                                       ^" in new self::B::•<core::num*>() as{TypeError} self::B<(core::num*) →* void>* : null;
-  self::B<core::Object*>* z = let final self::C<core::num*>* #t7 = c in let final dynamic #t8 = #t7.{self::C::x} as{TypeError} self::B<(core::num*) →* void>* in #t8.{core::Object::==}(null) ?{self::B<core::Object*>*} #t7.{self::C::x} = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:23:63: Error: A value of type 'B<num>' can't be assigned to a variable of type 'B<void Function(num)>'.
+  self::B<core::Object*>* z = let final self::C<core::num*>* #t7 = c in let final self::B<(core::num*) →* void>* #t8 = #t7.{self::C::x} as{TypeError} self::B<(core::num*) →* void>* in #t8.{core::Object::==}(null) ?{self::B<core::Object*>*} #t7.{self::C::x} = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:23:63: 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'.
 Try changing the type of the left hand side, or casting the right hand side to 'B<void Function(num)>'.
   var z = c. /*@ checkReturn=B<(num*) ->* void>* */ x ??= new B<num>();
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 3b5cd11..4a65ddd 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,15 +2,15 @@
 //
 // Problems in library:
 //
-// 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)>'.
+// 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)>'.
 //  - 'B' is from 'pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart'.
-// Try changing the type of the left hand side, or casting the right hand side to 'B<void Function(num)>'.
+// Try changing the type of the parameter, or casting the argument to 'B<void Function(num)>'.
 //   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: A value of type 'B<num>' can't be assigned to a variable of type 'B<void Function(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)>'.
 //  - 'B' is from 'pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart'.
-// Try changing the type of the left hand side, or casting the right hand side to 'B<void Function(num)>'.
+// Try changing the type of the parameter, or casting the argument to 'B<void Function(num)>'.
 //   var y = c. /*@ checkReturn=B<(num*) ->* void>* */ x += new B<num>();
 //                                                              ^
 //
@@ -46,14 +46,14 @@
   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: A value of type 'B<num>' can't be assigned to a variable of 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: The argument type 'B<num>' can't be assigned to the parameter type 'B<void Function(num)>'.
  - 'B' is from 'pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart'.
-Try changing the type of the left hand side, or casting the right hand side to 'B<void Function(num)>'.
+Try changing the type of the parameter, or casting the argument to 'B<void Function(num)>'.
   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: A value of type 'B<num>' can't be assigned to a variable of 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: The argument type 'B<num>' can't be assigned to the parameter type 'B<void Function(num)>'.
  - 'B' is from 'pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart'.
-Try changing the type of the left hand side, or casting the right hand side to 'B<void Function(num)>'.
+Try changing the type of the parameter, or casting the argument to 'B<void Function(num)>'.
   var y = c. /*@ checkReturn=B<(num*) ->* void>* */ x += new B<num>();
                                                              ^" in new self::B::•<core::num*>() as{TypeError} self::B<(core::num*) →* void>*);
   let final self::C<core::num*>* #t5 = c in (#t5.{self::C::x} as{TypeError} self::B<(core::num*) →* void>*).{core::Object::==}(null) ?{self::B<core::Object*>*} #t5.{self::C::x} = let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:22:55: Error: A value of type 'B<num>' can't be assigned to a variable of type 'B<void Function(num)>'.
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.strong.expect
index 1f89703..53d1c58 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.strong.expect
@@ -22,7 +22,7 @@
   c.{self::C::[]=}(0, new self::B::•<(core::num*) →* void>());
   let final self::C<core::num*>* #t1 = c in let final core::int* #t2 = 0 in #t1.{self::C::[]=}(#t2, (#t1.{self::C::[]}(#t2) as{TypeError} self::B<(core::num*) →* void>*).{self::B::+}(new self::B::•<(core::num*) →* void>()));
   self::B<(core::num*) →* void>* x = let final self::C<core::num*>* #t3 = c in let final core::int* #t4 = 0 in let final self::B<(core::num*) →* void>* #t5 = (#t3.{self::C::[]}(#t4) as{TypeError} self::B<(core::num*) →* void>*).{self::B::+}(new self::B::•<(core::num*) →* void>()) in let final void #t6 = #t3.{self::C::[]=}(#t4, #t5) in #t5;
-  let final self::C<core::num*>* #t7 = c in let final core::int* #t8 = 0 in (#t7.{self::C::[]}(#t8) as{TypeError} self::B<(core::num*) →* void>*).{core::Object::==}(null) ?{self::B<(core::num*) →* void>*} let final self::B<(core::num*) →* void>* #t9 = new self::B::•<(core::num*) →* void>() in let final void #t10 = #t7.{self::C::[]=}(#t8, #t9) in #t9 : null;
-  self::B<(core::num*) →* void>* y = let final self::C<core::num*>* #t11 = c in let final core::int* #t12 = 0 in let final self::B<(core::num*) →* void>* #t13 = #t11.{self::C::[]}(#t12) as{TypeError} self::B<(core::num*) →* void>* in #t13.{core::Object::==}(null) ?{self::B<(core::num*) →* void>*} let final self::B<(core::num*) →* void>* #t14 = new self::B::•<(core::num*) →* void>() in let final void #t15 = #t11.{self::C::[]=}(#t12, #t14) in #t14 : #t13;
+  let final self::C<core::num*>* #t7 = c in let final core::int* #t8 = 0 in (#t7.{self::C::[]}(#t8) as{TypeError} self::B<(core::num*) →* void>*).{core::Object::==}(null) ?{self::B<(core::num*) →* void>*} #t7.{self::C::[]=}(#t8, new self::B::•<(core::num*) →* void>()) : null;
+  self::B<(core::num*) →* void>* y = let final self::C<core::num*>* #t9 = c in let final core::int* #t10 = 0 in let final self::B<(core::num*) →* void>* #t11 = #t9.{self::C::[]}(#t10) as{TypeError} self::B<(core::num*) →* void>* in #t11.{core::Object::==}(null) ?{self::B<(core::num*) →* void>*} let final self::B<(core::num*) →* void>* #t12 = new self::B::•<(core::num*) →* void>() in let final void #t13 = #t9.{self::C::[]=}(#t10, #t12) in #t12 : #t11;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.strong.transformed.expect
index 1f89703..53d1c58 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.strong.transformed.expect
@@ -22,7 +22,7 @@
   c.{self::C::[]=}(0, new self::B::•<(core::num*) →* void>());
   let final self::C<core::num*>* #t1 = c in let final core::int* #t2 = 0 in #t1.{self::C::[]=}(#t2, (#t1.{self::C::[]}(#t2) as{TypeError} self::B<(core::num*) →* void>*).{self::B::+}(new self::B::•<(core::num*) →* void>()));
   self::B<(core::num*) →* void>* x = let final self::C<core::num*>* #t3 = c in let final core::int* #t4 = 0 in let final self::B<(core::num*) →* void>* #t5 = (#t3.{self::C::[]}(#t4) as{TypeError} self::B<(core::num*) →* void>*).{self::B::+}(new self::B::•<(core::num*) →* void>()) in let final void #t6 = #t3.{self::C::[]=}(#t4, #t5) in #t5;
-  let final self::C<core::num*>* #t7 = c in let final core::int* #t8 = 0 in (#t7.{self::C::[]}(#t8) as{TypeError} self::B<(core::num*) →* void>*).{core::Object::==}(null) ?{self::B<(core::num*) →* void>*} let final self::B<(core::num*) →* void>* #t9 = new self::B::•<(core::num*) →* void>() in let final void #t10 = #t7.{self::C::[]=}(#t8, #t9) in #t9 : null;
-  self::B<(core::num*) →* void>* y = let final self::C<core::num*>* #t11 = c in let final core::int* #t12 = 0 in let final self::B<(core::num*) →* void>* #t13 = #t11.{self::C::[]}(#t12) as{TypeError} self::B<(core::num*) →* void>* in #t13.{core::Object::==}(null) ?{self::B<(core::num*) →* void>*} let final self::B<(core::num*) →* void>* #t14 = new self::B::•<(core::num*) →* void>() in let final void #t15 = #t11.{self::C::[]=}(#t12, #t14) in #t14 : #t13;
+  let final self::C<core::num*>* #t7 = c in let final core::int* #t8 = 0 in (#t7.{self::C::[]}(#t8) as{TypeError} self::B<(core::num*) →* void>*).{core::Object::==}(null) ?{self::B<(core::num*) →* void>*} #t7.{self::C::[]=}(#t8, new self::B::•<(core::num*) →* void>()) : null;
+  self::B<(core::num*) →* void>* y = let final self::C<core::num*>* #t9 = c in let final core::int* #t10 = 0 in let final self::B<(core::num*) →* void>* #t11 = #t9.{self::C::[]}(#t10) as{TypeError} self::B<(core::num*) →* void>* in #t11.{core::Object::==}(null) ?{self::B<(core::num*) →* void>*} let final self::B<(core::num*) →* void>* #t12 = new self::B::•<(core::num*) →* void>() in let final void #t13 = #t9.{self::C::[]=}(#t10, #t12) in #t12 : #t11;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect
index 2d52e9b..9587cd5 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect
@@ -72,12 +72,12 @@
   }
 }
 static method test(self::I<core::Object*>* i) → void {
-  self::expectTypeError(() → core::Null* {
+  self::expectTypeError(() → core::Null? {
     i.{self::I::x} = "hello";
   });
   i.{self::I::x} = 1;
   self::expect(i.{self::I::x}, 1);
-  self::expectTypeError(() → core::Null* {
+  self::expectTypeError(() → core::Null? {
     i.{self::I::y} = "hello";
   });
   i.{self::I::y} = 2;
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect
index a3d75db..067ee48 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect
@@ -81,12 +81,12 @@
   }
 }
 static method test(self::I<core::Object*>* i) → void {
-  self::expectTypeError(() → core::Null* {
+  self::expectTypeError(() → core::Null? {
     i.{self::I::x} = "hello";
   });
   i.{self::I::x} = 2;
   self::expect(i.{self::I::x}, 1);
-  self::expectTypeError(() → core::Null* {
+  self::expectTypeError(() → core::Null? {
     i.{self::I::y} = "hello";
   });
   i.{self::I::y} = 4;
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_checked_via_target.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/stub_checked_via_target.dart.strong.expect
index c533269..ab4a68c 100644
--- a/pkg/front_end/testcases/runtime_checks_new/stub_checked_via_target.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/stub_checked_via_target.dart.strong.expect
@@ -41,11 +41,11 @@
   c.{self::C::f}("hello");
 }
 static method test(self::C* c, self::I* i) → void {
-  self::expectTypeError(() → core::Null* {
+  self::expectTypeError(() → core::Null? {
     i.{self::I::f}("hello");
   });
   self::expect(i.{self::I::f}(1), 2);
-  self::expectTypeError(() → core::Null* {
+  self::expectTypeError(() → core::Null? {
     c.{self::C::f}("hello");
   });
   self::expect(c.{self::C::f}(1), 2);
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_checked_via_target.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_checked_via_target.dart.strong.transformed.expect
index c533269..ab4a68c 100644
--- a/pkg/front_end/testcases/runtime_checks_new/stub_checked_via_target.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/stub_checked_via_target.dart.strong.transformed.expect
@@ -41,11 +41,11 @@
   c.{self::C::f}("hello");
 }
 static method test(self::C* c, self::I* i) → void {
-  self::expectTypeError(() → core::Null* {
+  self::expectTypeError(() → core::Null? {
     i.{self::I::f}("hello");
   });
   self::expect(i.{self::I::f}(1), 2);
-  self::expectTypeError(() → core::Null* {
+  self::expectTypeError(() → core::Null? {
     c.{self::C::f}("hello");
   });
   self::expect(c.{self::C::f}(1), 2);
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index df68cb5..c52e649 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -53,6 +53,7 @@
 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/unsound_promotion: RuntimeError
@@ -79,7 +80,6 @@
 inference/generic_methods_infer_js_builtin: InstrumentationMismatch # Issue #30029
 inference/inconsistent_overrides: TypeCheckError
 inference/infer_field_override_multiple: TypeCheckError
-inference/infer_from_complex_expressions_if_outer_most_value_is_precise: TypeCheckError # Issue #35630
 inference/infer_method_missing_params: ExpectationFileMismatch # Not supposed to be able to infer types if supertypes disagree on number of parameters. An error may be missing as C.f and B.f are not compatible at all.
 inference/infer_method_missing_params: TypeCheckError
 inference/infer_type_regardless_of_declaration_order_or_cycles: RuntimeError
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 35ef84e..8d0e382 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -8,6 +8,7 @@
 
 expression/eval: TextSerializationFailure # Was: Pass
 expression/main: TextSerializationFailure # Was: Pass
+extensions/compounds: TextSerializationFailure
 extensions/direct_instance_access: TextSerializationFailure
 extensions/direct_static_access: TextSerializationFailure
 extensions/explicit_extension_access: TextSerializationFailure
@@ -24,6 +25,7 @@
 extensions/instance_tearoff: TextSerializationFailure
 extensions/invalid_explicit_access: TextSerializationFailure
 extensions/nested_on_types: TextSerializationFailure
+extensions/null_aware: TextSerializationFailure
 extensions/on_type_inference: TextSerializationFailure
 extensions/on_type_variable_inference: TextSerializationFailure
 extensions/operators: TextSerializationFailure
@@ -31,6 +33,7 @@
 extensions/static_access: TextSerializationFailure
 extensions/static_access_of_instance: TextSerializationFailure
 extensions/type_variables: TextSerializationFailure
+extensions/unnamed_extensions: TextSerializationFailure
 extensions/use_this: TextSerializationFailure
 general/error_locations/error_location_01: TextSerializationFailure
 general/error_locations/error_location_02: TextSerializationFailure
@@ -94,6 +97,7 @@
 general/closure: TextSerializationFailure # Was: Pass
 general/co19_language_metadata_syntax_t04: TextSerializationFailure # Was: Pass
 general/complex_class_hierarchy: TextSerializationFailure
+general/compound_binary_implicit_as: TextSerializationFailure
 general/constructor_const_inference: TextSerializationFailure # Was: Pass
 general/constructor_cycle: TextSerializationFailure # Was: Pass
 general/constructor_function_types: TextSerializationFailure # Was: Pass
@@ -183,10 +187,13 @@
 general/named_parameters: TextSerializationFailure # Was: Pass
 general/native_as_name: TextSerializationFailure # Was: Pass
 general/nested_implicit_const_with_env_var: TextSerializationFailure # Was: Pass
+general/nested_property_set: TextSerializationFailure
+general/nested_variable_set: TextSerializationFailure
 general/no_such_method_private_setter: TextSerializationFailure # Was: Pass
 general/no_such_method_private_setter_lib: TextSerializationFailure # Was: Pass
 general/non_covariant_checks: TextSerializationFailure
 general/null_aware: TextSerializationFailure # Was: Pass
+general/null_aware_for_in: TextSerializationFailure
 general/operator_method_not_found: TextSerializationFailure
 general/operators: TextSerializationFailure # Was: Pass
 general/optional: TypeCheckError
@@ -247,6 +254,7 @@
 general/top_level_accessors_part: TextSerializationFailure # Was: Pass
 general/top_level_library_method: TextSerializationFailure # Was: Pass
 general/type_of_null: TextSerializationFailure
+general/type_variable_bound_access: TypeCheckError
 general/type_parameter_type_named_int: TextSerializationFailure
 general/type_variable_as_super: TextSerializationFailure # Was: RuntimeError
 general/type_variable_prefix: TextSerializationFailure # Was: RuntimeError
@@ -468,7 +476,7 @@
 inference/infer_final_field_getter_and_setter: TextSerializationFailure # Was: Pass
 inference/infer_final_field_getter_only: TextSerializationFailure # Was: Pass
 inference/infer_final_field_setter_only: TextSerializationFailure # Was: Pass
-inference/infer_from_complex_expressions_if_outer_most_value_is_precise: TypeCheckError # Issue #35630
+inference/infer_from_complex_expressions_if_outer_most_value_is_precise: TextSerializationFailure
 inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2: TextSerializationFailure # Was: Pass
 inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields: TextSerializationFailure # Was: Pass
 inference/infer_from_variables_in_cycle_libs_when_flag_is_on2: TextSerializationFailure # Was: Pass
@@ -828,6 +836,7 @@
 instantiate_to_bound/typedef_raw_in_bound: TextSerializationFailure # Was: Pass
 instantiate_to_bound/typedef_super_bounded_type: TextSerializationFailure # Was: Pass
 new_const_insertion/simple: TextSerializationFailure # Was: Pass
+nnbd/function_types: TextSerializationFailure
 nnbd/late: TextSerializationFailure
 nnbd/nullable_param: TextSerializationFailure
 nnbd/required: TextSerializationFailure
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index 98ea35d..619c986 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -249,6 +249,8 @@
   "--omit-platform": false,
   "--fatal": ",",
   "--help": false,
+  // TODO(johnniwinther): Remove legacy option flags. Legacy mode is no longer
+  // supported.
   "--legacy": "--legacy-mode",
   "--legacy-mode": false,
   "--libraries-json": Uri,
@@ -299,11 +301,9 @@
         "Can't specify both '--compile-sdk' and '--platform'.");
   }
 
-  final bool legacyMode = options["--legacy-mode"];
-
   final String targetName = options["--target"] ?? "vm";
 
-  final TargetFlags flags = new TargetFlags(legacyMode: legacyMode);
+  final TargetFlags flags = new TargetFlags();
 
   final Target target = getTarget(targetName, flags);
   if (target == null) {
@@ -377,7 +377,6 @@
           ..setExitCodeOnProblem = true
           ..fileSystem = fileSystem
           ..packagesFileUri = packages
-          ..legacyMode = legacyMode
           ..target = target
           ..throwOnErrorsForDebugging = errorsAreFatal
           ..throwOnWarningsForDebugging = warningsAreFatal
@@ -410,7 +409,9 @@
       case 'dart2js_server':
         return 'dart2js_platform.dill';
       case 'vm':
-        return legacyMode ? 'vm_platform.dill' : "vm_platform_strong.dill";
+        // TODO(johnniwinther): Stop generating 'vm_platform.dill' and rename
+        // 'vm_platform_strong.dill' to 'vm_platform.dill'.
+        return "vm_platform_strong.dill";
       case 'none':
         return "vm_platform_strong.dill";
       default:
@@ -432,7 +433,6 @@
     ..sdkRoot = sdk
     ..sdkSummary = platform
     ..packagesFileUri = packages
-    ..legacyMode = legacyMode
     ..target = target
     ..throwOnErrorsForDebugging = errorsAreFatal
     ..throwOnWarningsForDebugging = warningsAreFatal
diff --git a/pkg/front_end/tool/compare_dill.dart b/pkg/front_end/tool/compare_dill.dart
new file mode 100644
index 0000000..1711ed5
--- /dev/null
+++ b/pkg/front_end/tool/compare_dill.dart
@@ -0,0 +1,46 @@
+import 'dart:io' show File;
+
+import '../test/binary_md_dill_reader.dart' show DillComparer;
+
+import '../test/utils/io_utils.dart' show computeRepoDir;
+
+main(List<String> args) {
+  if (args.length != 2) {
+    throw "Expects two arguments: The two files to compare";
+  }
+  File fileA = new File(args[0]);
+  File fileB = new File(args[1]);
+
+  List<int> a = fileA.readAsBytesSync();
+  List<int> b = fileB.readAsBytesSync();
+
+  bool shouldCompare = false;
+  if (a.length != b.length) {
+    print("Input lengths are different.");
+    shouldCompare = true;
+  } else {
+    for (int i = 0; i < a.length; ++i) {
+      if (a[i] != b[i]) {
+        print("Data differs at byte ${i + 1}.");
+        shouldCompare = true;
+      }
+    }
+  }
+
+  if (shouldCompare) {
+    StringBuffer message = new StringBuffer();
+    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.");
+    }
+
+    print(message);
+  } else {
+    print("Inputs byte-equal!");
+  }
+}
diff --git a/pkg/front_end/tool/fasta_perf.dart b/pkg/front_end/tool/fasta_perf.dart
index 577d582..3ad1726 100644
--- a/pkg/front_end/tool/fasta_perf.dart
+++ b/pkg/front_end/tool/fasta_perf.dart
@@ -36,11 +36,10 @@
     print(argParser.usage);
     exit(1);
   }
-  bool legacyMode = options['legacy'];
   var bench = options.rest[0];
   var entryUri = Uri.base.resolve(options.rest[1]);
 
-  await setup(entryUri, legacyMode: legacyMode);
+  await setup(entryUri);
 
   Map<Uri, List<int>> files = await scanReachableFiles(entryUri);
   var handlers = {
@@ -48,10 +47,10 @@
     // TODO(sigmund): enable when we can run the ast-builder standalone.
     // 'parse': () async => parseFiles(files),
     'kernel_gen_e2e': () async {
-      await generateKernel(entryUri, legacyMode: legacyMode);
+      await generateKernel(entryUri);
     },
     'kernel_gen_e2e_sum': () async {
-      await generateKernel(entryUri, compileSdk: false, legacyMode: legacyMode);
+      await generateKernel(entryUri, compileSdk: false);
     },
   };
 
@@ -90,15 +89,15 @@
 
 /// Preliminary set up to be able to correctly resolve URIs on the given
 /// program.
-Future setup(Uri entryUri, {bool legacyMode: false}) async {
+Future setup(Uri entryUri) async {
   var options = new CompilerOptions()
     ..sdkRoot = sdkRoot
     // Because this is only used to create a uriResolver, we don't allow any
     // whitelisting of error messages in the error handler.
-    ..onDiagnostic = onDiagnosticMessageHandler(legacyMode: true)
+    ..onDiagnostic = onDiagnosticMessageHandler()
     ..compileSdk = true
     ..packagesFileUri = Uri.base.resolve('.packages')
-    ..target = createTarget(isFlutter: false, legacyMode: legacyMode);
+    ..target = createTarget(isFlutter: false);
   uriResolver = await new ProcessedOptions(options: options).getUriTranslator();
 }
 
@@ -225,8 +224,7 @@
 }
 
 // Invoke the fasta kernel generator for the program starting in [entryUri]
-generateKernel(Uri entryUri,
-    {bool compileSdk: true, bool legacyMode: false}) async {
+generateKernel(Uri entryUri, {bool compileSdk: true}) async {
   // TODO(sigmund): this is here only to compute the input size,
   // we should extract the input size from the frontend instead.
   await scanReachableFiles(entryUri);
@@ -234,9 +232,8 @@
   var timer = new Stopwatch()..start();
   var options = new CompilerOptions()
     ..sdkRoot = sdkRoot
-    ..onDiagnostic = onDiagnosticMessageHandler(legacyMode: legacyMode)
-    ..legacyMode = legacyMode
-    ..target = createTarget(isFlutter: false, legacyMode: legacyMode)
+    ..onDiagnostic = onDiagnosticMessageHandler()
+    ..target = createTarget(isFlutter: false)
     ..packagesFileUri = Uri.base.resolve('.packages')
     ..compileSdk = compileSdk
     ..environmentDefines = const {};
@@ -267,6 +264,8 @@
 }
 
 ArgParser argParser = new ArgParser()
+  // TODO(johnniwinther): Remove legacy option. Legacy mode is no longer
+  //  supported.
   ..addFlag('legacy',
       help: 'run the compiler in legacy-mode',
       defaultsTo: false,
diff --git a/pkg/front_end/tool/incremental_perf.dart b/pkg/front_end/tool/incremental_perf.dart
index 1d1ddfd..7d87595 100644
--- a/pkg/front_end/tool/incremental_perf.dart
+++ b/pkg/front_end/tool/incremental_perf.dart
@@ -72,7 +72,6 @@
       parse(jsonDecode(new File.fromUri(editsUri).readAsStringSync()));
   bool verbose = options["verbose"];
   bool verboseCompilation = options["verbose-compilation"];
-  bool legacyMode = options["mode"] == "legacy";
   bool isFlutter = options["target"] == "flutter";
   bool useMinimalGenerator = options["implementation"] == "minimal";
   TimingsCollector collector = new TimingsCollector(verbose);
@@ -81,7 +80,6 @@
     await benchmark(
         collector,
         entryUri,
-        legacyMode,
         isFlutter,
         useMinimalGenerator,
         verbose,
@@ -98,7 +96,6 @@
 Future benchmark(
     TimingsCollector collector,
     Uri entryUri,
-    bool legacyMode,
     bool isFlutter,
     bool useMinimalGenerator,
     bool verbose,
@@ -111,9 +108,8 @@
   var compilerOptions = new CompilerOptions()
     ..verbose = verboseCompilation
     ..fileSystem = overlayFs
-    ..legacyMode = legacyMode
-    ..onDiagnostic = onDiagnosticMessageHandler(legacyMode: legacyMode)
-    ..target = createTarget(isFlutter: isFlutter, legacyMode: legacyMode)
+    ..onDiagnostic = onDiagnosticMessageHandler()
+    ..target = createTarget(isFlutter: isFlutter)
     ..environmentDefines = const {};
   if (sdkSummary != null) {
     compilerOptions.sdkSummary = _resolveOverlayUri(sdkSummary);
@@ -301,6 +297,8 @@
       help: 'caching policy used by the compiler',
       defaultsTo: 'protected',
       allowed: ['evicting', 'memory', 'protected'])
+  // TODO(johnniwinther): Remove mode option. Legacy mode is no longer
+  // supported.
   ..addOption('mode',
       help: 'whether to run in strong or legacy mode',
       defaultsTo: 'strong',
diff --git a/pkg/front_end/tool/perf_common.dart b/pkg/front_end/tool/perf_common.dart
index 67f93a9..5a8db5e 100644
--- a/pkg/front_end/tool/perf_common.dart
+++ b/pkg/front_end/tool/perf_common.dart
@@ -48,13 +48,12 @@
   fastaCodes.codeUndefinedMethod,
 ]);
 
-DiagnosticMessageHandler onDiagnosticMessageHandler({bool legacyMode: false}) {
+DiagnosticMessageHandler onDiagnosticMessageHandler() {
   bool messageReported = false;
   return (DiagnosticMessage m) {
     if (m.severity == Severity.internalProblem ||
         m.severity == Severity.error) {
-      if (legacyMode ||
-          !whitelistMessageCode.contains(getMessageCodeObject(m))) {
+      if (!whitelistMessageCode.contains(getMessageCodeObject(m))) {
         printDiagnosticMessage(m, stderr.writeln);
         exitCode = 1;
       } else if (!messageReported) {
@@ -70,8 +69,8 @@
 // TODO(sigmund): delete as soon as the disableTypeInference flag and the
 // legacyMode flag get merged, and we have a single way of specifying the
 // legacy-mode flag to the FE.
-Target createTarget({bool isFlutter: false, bool legacyMode: false}) {
-  var flags = new TargetFlags(legacyMode: legacyMode);
+Target createTarget({bool isFlutter: false}) {
+  TargetFlags flags = new TargetFlags();
   if (isFlutter) {
     return new FlutterTarget(flags);
   } else {
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index cad20ee..337d47d 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -143,7 +143,7 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 31;
+  UInt32 formatVersion = 32;
   List<String> problemsAsJson; // Described in problems.md.
   Library[] libraries;
   UriSource sourceMap;
@@ -228,7 +228,7 @@
 }
 
 type Library {
-  Byte flags (isExternal, isSynthetic);
+  Byte flags (isExternal, isSynthetic, isNonNullableByDefault);
   UInt languageVersionMajor;
   UInt languageVersionMinor;
   CanonicalNameReference canonicalName;
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 4f83479..ae961e9 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -64,6 +64,7 @@
 ///
 library kernel.ast;
 
+import 'dart:collection' show ListBase;
 import 'dart:convert' show utf8;
 
 import 'visitor.dart';
@@ -116,7 +117,7 @@
 
   R accept<R>(TreeVisitor<R> v);
   void visitChildren(Visitor v);
-  transformChildren(Transformer v);
+  void transformChildren(Transformer v);
 
   /// Replaces [child] with [replacement].
   ///
@@ -200,7 +201,38 @@
 class Reference {
   CanonicalName canonicalName;
 
-  NamedNode node;
+  NamedNode _node;
+
+  NamedNode get node {
+    if (_node == null) {
+      // Either this is an unbound reference or it belongs to a lazy-loaded
+      // (and not yet loaded) class. If it belongs to a lazy-loaded class,
+      // load the class.
+
+      CanonicalName canonicalNameParent = canonicalName?.parent;
+      while (canonicalNameParent != null) {
+        if (canonicalNameParent.name.startsWith("@")) {
+          break;
+        }
+        canonicalNameParent = canonicalNameParent.parent;
+      }
+      if (canonicalNameParent != null) {
+        NamedNode parentNamedNode =
+            canonicalNameParent?.parent?.reference?._node;
+        if (parentNamedNode is Class) {
+          Class parentClass = parentNamedNode;
+          if (parentClass.lazyBuilder != null) {
+            parentClass.ensureLoaded();
+          }
+        }
+      }
+    }
+    return _node;
+  }
+
+  void set node(NamedNode node) {
+    _node = node;
+  }
 
   String toString() {
     if (canonicalName != null) {
@@ -298,6 +330,7 @@
 
   static const int ExternalFlag = 1 << 0;
   static const int SyntheticFlag = 1 << 1;
+  static const int NonNullableByDefaultFlag = 1 << 2;
 
   int flags = 0;
 
@@ -322,6 +355,13 @@
     flags = value ? (flags | SyntheticFlag) : (flags & ~SyntheticFlag);
   }
 
+  bool get isNonNullableByDefault => (flags & NonNullableByDefaultFlag) != 0;
+  void set isNonNullableByDefault(bool value) {
+    flags = value
+        ? (flags | NonNullableByDefaultFlag)
+        : (flags & ~NonNullableByDefaultFlag);
+  }
+
   String name;
 
   /// Problems in this [Library] encoded as json objects.
@@ -380,6 +420,23 @@
     setParents(this.fields, this);
   }
 
+  Nullability get nullable {
+    return isNonNullableByDefault ? Nullability.nullable : Nullability.legacy;
+  }
+
+  Nullability get nonNullable {
+    return isNonNullableByDefault
+        ? Nullability.nonNullable
+        : Nullability.legacy;
+  }
+
+  Nullability nullableIfTrue(bool isNullable) {
+    if (isNonNullableByDefault) {
+      return isNullable ? Nullability.nullable : Nullability.nonNullable;
+    }
+    return Nullability.legacy;
+  }
+
   /// Returns the top-level fields and procedures defined in this library.
   ///
   /// This getter is for convenience, not efficiency.  Consider manually
@@ -745,6 +802,41 @@
   Body,
 }
 
+/// List-wrapper that marks the parent-class as dirty if the list is modified.
+///
+/// The idea being, that for non-dirty classes (classes just loaded from dill)
+/// the canonical names has already been calculated, and recalculating them is
+/// not needed. If, however, we change anything, recalculation of the canonical
+/// names can be needed.
+class DirtifyingList<E> extends ListBase<E> {
+  final Class dirtifyClass;
+  final List<E> wrapped;
+
+  DirtifyingList(this.dirtifyClass, this.wrapped);
+
+  @override
+  int get length {
+    return wrapped.length;
+  }
+
+  @override
+  void set length(int length) {
+    dirtifyClass.dirty = true;
+    wrapped.length = length;
+  }
+
+  @override
+  E operator [](int index) {
+    return wrapped[index];
+  }
+
+  @override
+  void operator []=(int index, E value) {
+    dirtifyClass.dirty = true;
+    wrapped[index] = value;
+  }
+}
+
 /// Declaration of a regular class or a mixin application.
 ///
 /// Mixin applications may not contain fields or procedures, as they implicitly
@@ -885,23 +977,92 @@
   /// The types from the `implements` clause.
   final List<Supertype> implementedTypes;
 
+  /// 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.
+  void Function() lazyBuilder;
+
+  /// Makes sure the class is loaded, i.e. the fields, procedures etc have been
+  /// loaded from the dill. Generally, one should not need to call this as it is
+  /// done automatically when accessing the lists.
+  void ensureLoaded() {
+    if (lazyBuilder != null) {
+      var lazyBuilderLocal = lazyBuilder;
+      lazyBuilder = null;
+      lazyBuilderLocal();
+    }
+  }
+
+  /// Internal. Should *ONLY* be used from within kernel.
+  ///
+  /// Used for adding fields when reading the dill file.
+  final List<Field> fieldsInternal;
+  DirtifyingList<Field> _fieldsView;
+
   /// Fields declared in the class.
   ///
   /// For mixin applications this should be empty.
-  final List<Field> fields;
+  List<Field> get fields {
+    ensureLoaded();
+    // If already dirty the caller just might as well add stuff directly too.
+    if (dirty) return fieldsInternal;
+    _fieldsView ??= new DirtifyingList(this, fieldsInternal);
+    return _fieldsView;
+  }
+
+  /// Internal. Should *ONLY* be used from within kernel.
+  ///
+  /// Used for adding constructors when reading the dill file.
+  final List<Constructor> constructorsInternal;
+  DirtifyingList<Constructor> _constructorsView;
 
   /// Constructors declared in the class.
-  final List<Constructor> constructors;
+  List<Constructor> get constructors {
+    ensureLoaded();
+    // If already dirty the caller just might as well add stuff directly too.
+    if (dirty) return constructorsInternal;
+    _constructorsView ??= new DirtifyingList(this, constructorsInternal);
+    return _constructorsView;
+  }
+
+  /// Internal. Should *ONLY* be used from within kernel.
+  ///
+  /// Used for adding procedures when reading the dill file.
+  final List<Procedure> proceduresInternal;
+  DirtifyingList<Procedure> _proceduresView;
 
   /// Procedures declared in the class.
   ///
   /// For mixin applications this should only contain forwarding stubs.
-  final List<Procedure> procedures;
+  List<Procedure> get procedures {
+    ensureLoaded();
+    // If already dirty the caller just might as well add stuff directly too.
+    if (dirty) return proceduresInternal;
+    _proceduresView ??= new DirtifyingList(this, proceduresInternal);
+    return _proceduresView;
+  }
+
+  /// Internal. Should *ONLY* be used from within kernel.
+  ///
+  /// Used for adding redirecting factory constructor when reading the dill
+  /// file.
+  final List<RedirectingFactoryConstructor>
+      redirectingFactoryConstructorsInternal;
+  DirtifyingList<RedirectingFactoryConstructor>
+      _redirectingFactoryConstructorsView;
 
   /// Redirecting factory constructors declared in the class.
   ///
   /// For mixin applications this should be empty.
-  final List<RedirectingFactoryConstructor> redirectingFactoryConstructors;
+  List<RedirectingFactoryConstructor> get redirectingFactoryConstructors {
+    ensureLoaded();
+    // If already dirty the caller just might as well add stuff directly too.
+    if (dirty) return redirectingFactoryConstructorsInternal;
+    _redirectingFactoryConstructorsView ??=
+        new DirtifyingList(this, redirectingFactoryConstructorsInternal);
+    return _redirectingFactoryConstructorsView;
+  }
 
   Class(
       {this.name,
@@ -919,23 +1080,24 @@
       Reference reference})
       : this.typeParameters = typeParameters ?? <TypeParameter>[],
         this.implementedTypes = implementedTypes ?? <Supertype>[],
-        this.fields = fields ?? <Field>[],
-        this.constructors = constructors ?? <Constructor>[],
-        this.procedures = procedures ?? <Procedure>[],
-        this.redirectingFactoryConstructors =
+        this.fieldsInternal = fields ?? <Field>[],
+        this.constructorsInternal = constructors ?? <Constructor>[],
+        this.proceduresInternal = procedures ?? <Procedure>[],
+        this.redirectingFactoryConstructorsInternal =
             redirectingFactoryConstructors ?? <RedirectingFactoryConstructor>[],
         super(reference) {
     setParents(this.typeParameters, this);
-    setParents(this.constructors, this);
-    setParents(this.procedures, this);
-    setParents(this.fields, this);
-    setParents(this.redirectingFactoryConstructors, this);
+    setParents(this.constructorsInternal, this);
+    setParents(this.proceduresInternal, this);
+    setParents(this.fieldsInternal, this);
+    setParents(this.redirectingFactoryConstructorsInternal, this);
     this.isAbstract = isAbstract;
     this.isAnonymousMixin = isAnonymousMixin;
   }
 
   void computeCanonicalNames() {
     assert(canonicalName != null);
+    if (!dirty) return;
     for (int i = 0; i < fields.length; ++i) {
       Field member = fields[i];
       canonicalName.getChildFromMember(member).bindTo(member.reference);
@@ -952,6 +1114,7 @@
       RedirectingFactoryConstructor member = redirectingFactoryConstructors[i];
       canonicalName.getChildFromMember(member).bindTo(member.reference);
     }
+    dirty = false;
   }
 
   /// The immediate super class, or `null` if this is the root class.
@@ -1008,20 +1171,27 @@
   /// The library containing this class.
   Library get enclosingLibrary => parent;
 
+  /// Internal. Should *ONLY* be used from within kernel.
+  ///
+  /// If true we have to compute canonical names for all children of this class.
+  /// if false we can skip it.
+  bool dirty = true;
+
   /// Adds a member to this class.
   ///
   /// Throws an error if attempting to add a field or procedure to a mixin
   /// application.
   void addMember(Member member) {
+    dirty = true;
     member.parent = this;
     if (member is Constructor) {
-      constructors.add(member);
+      constructorsInternal.add(member);
     } else if (member is Procedure) {
-      procedures.add(member);
+      proceduresInternal.add(member);
     } else if (member is Field) {
-      fields.add(member);
+      fieldsInternal.add(member);
     } else if (member is RedirectingFactoryConstructor) {
-      redirectingFactoryConstructors.add(member);
+      redirectingFactoryConstructorsInternal.add(member);
     } else {
       throw new ArgumentError(member);
     }
@@ -1054,9 +1224,6 @@
     return new Supertype(this, _getAsTypeArguments(typeParameters));
   }
 
-  InterfaceType _rawType;
-  InterfaceType get rawType => _rawType ??= new InterfaceType(this);
-
   InterfaceType _thisType;
   InterfaceType get thisType {
     return _thisType ??=
@@ -2302,7 +2469,15 @@
     return new NamedType(node.name, node.type, isRequired: node.isRequired);
   }
 
-  FunctionType get functionType {
+  /// Returns the function type of the node reusing its type parameters.
+  ///
+  /// This getter works similarly to [functionType], but reuses type parameters
+  /// of the function node (or the class enclosing it -- see the comment on
+  /// [functionType] about constructors of generic classes) in the result.  It
+  /// is useful in some contexts, especially when reasoning about the function
+  /// type of the enclosing generic function and in combination with
+  /// [FunctionType.withoutTypeParameters].
+  FunctionType get thisFunctionType {
     TreeNode parent = this.parent;
     List<NamedType> named =
         namedParameters.map(_getNamedTypeOfVariable).toList(growable: false);
@@ -2320,6 +2495,21 @@
         requiredParameterCount: requiredParameterCount);
   }
 
+  /// Returns the function type of the function node.
+  ///
+  /// If the function node describes a generic function, the resulting function
+  /// type will be generic.  If the function node describes a constructor of a
+  /// generic class, the resulting function type will be generic with its type
+  /// parameters constructed after those of the class.  In both cases, if the
+  /// resulting function type is generic, a fresh set of type parameters is used
+  /// in it.
+  FunctionType get functionType {
+    return typeParameters.isEmpty
+        ? thisFunctionType
+        : getFreshTypeParameters(typeParameters)
+            .applyToFunctionType(thisFunctionType);
+  }
+
   R accept<R>(TreeVisitor<R> v) => v.visitFunctionNode(this);
 
   visitChildren(Visitor v) {
@@ -2416,7 +2606,7 @@
     // subtypes of Object (not just interface types), and function types are
     // considered subtypes of Function.
     if (superclass.typeParameters.isEmpty) {
-      return superclass.rawType;
+      return types.coreTypes.legacyRawType(superclass);
     }
     var type = getStaticType(types);
     while (type is TypeParameterType) {
@@ -2432,7 +2622,7 @@
       return superclass.bottomType;
     }
     types.typeError(this, '$type is not a subtype of $superclass');
-    return superclass.rawType;
+    return types.coreTypes.legacyRawType(superclass);
   }
 
   R accept<R>(ExpressionVisitor<R> v);
@@ -3229,8 +3419,9 @@
 
   DartType getStaticType(TypeEnvironment types) {
     return arguments.types.isEmpty
-        ? target.enclosingClass.rawType
-        : new InterfaceType(target.enclosingClass, arguments.types);
+        ? types.coreTypes.legacyRawType(target.enclosingClass)
+        : new InterfaceType(
+            target.enclosingClass, arguments.types, Nullability.legacy);
   }
 
   R accept<R>(ExpressionVisitor<R> v) => v.visitConstructorInvocation(this);
@@ -3249,10 +3440,16 @@
     }
   }
 
+  // TODO(dmitryas): Change the getter into a method that accepts a CoreTypes.
   InterfaceType get constructedType {
+    Class enclosingClass = target.enclosingClass;
+    // TODO(dmitryas): Get raw type from a CoreTypes object if arguments is
+    // empty.
     return arguments.types.isEmpty
-        ? target.enclosingClass.rawType
-        : new InterfaceType(target.enclosingClass, arguments.types);
+        ? new InterfaceType(
+            enclosingClass, const <DartType>[], Nullability.legacy)
+        : new InterfaceType(
+            enclosingClass, arguments.types, Nullability.legacy);
   }
 }
 
@@ -3561,7 +3758,7 @@
 
   DartType getStaticType(TypeEnvironment types) {
     return typeArguments.isEmpty
-        ? classNode.rawType
+        ? types.coreTypes.legacyRawType(classNode)
         : new InterfaceType(classNode, typeArguments);
   }
 
@@ -4498,13 +4695,13 @@
   R accept1<R, A>(StatementVisitor1<R, A> v, A arg) =>
       v.visitForInStatement(this, arg);
 
-  visitChildren(Visitor v) {
+  void visitChildren(Visitor v) {
     variable?.accept(v);
     iterable?.accept(v);
     body?.accept(v);
   }
 
-  transformChildren(Transformer v) {
+  void transformChildren(Transformer v) {
     if (variable != null) {
       variable = variable.accept<TreeNode>(v);
       variable?.parent = this;
@@ -5901,6 +6098,7 @@
   DartType getType(TypeEnvironment types) => types.boolType;
 }
 
+/// An integer constant on a non-JS target.
 class IntConstant extends PrimitiveConstant<int> {
   IntConstant(int value) : super(value);
 
@@ -5911,6 +6109,7 @@
   DartType getType(TypeEnvironment types) => types.intType;
 }
 
+/// A double constant on a non-JS target or any numeric constant on a JS target.
 class DoubleConstant extends PrimitiveConstant<double> {
   DoubleConstant(double value) : super(value);
 
@@ -6326,6 +6525,14 @@
   }
 
   void unbindCanonicalNames() {
+    // TODO(jensj): Get rid of this.
+    for (int i = 0; i < libraries.length; i++) {
+      Library lib = libraries[i];
+      for (int j = 0; j < lib.classes.length; j++) {
+        Class c = lib.classes[j];
+        c.dirty = true;
+      }
+    }
     root.unbindAll();
   }
 
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 120d1bb..32f2210 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -87,11 +87,21 @@
   /// will not be resolved correctly.
   bool _disableLazyReading = false;
 
+  /// If binary contains metadata section with payloads referencing other nodes
+  /// such Kernel binary can't be read lazily because metadata cross references
+  /// will not be resolved correctly.
+  bool _disableLazyClassReading = false;
+
+  /// Note that [disableLazyClassReading] is incompatible
+  /// with checkCanonicalNames on readComponent.
   BinaryBuilder(this._bytes,
       {this.filename,
       bool disableLazyReading = false,
+      bool disableLazyClassReading = false,
       bool alwaysCreateNewNamedNodes})
       : _disableLazyReading = disableLazyReading,
+        _disableLazyClassReading =
+            disableLazyReading || disableLazyClassReading,
         this.alwaysCreateNewNamedNodes = alwaysCreateNewNamedNodes ?? false;
 
   fail(String message) {
@@ -460,6 +470,7 @@
     List<int> componentFileSizes = _indexComponents();
     if (componentFileSizes.length > 1) {
       _disableLazyReading = true;
+      _disableLazyClassReading = true;
     }
     int componentFileIndex = 0;
     while (_byteOffset < _bytes.length) {
@@ -479,6 +490,7 @@
     List<int> componentFileSizes = _indexComponents();
     if (componentFileSizes.length > 1) {
       _disableLazyReading = true;
+      _disableLazyClassReading = true;
     }
     int componentFileIndex = 0;
     while (_byteOffset < _bytes.length) {
@@ -687,6 +699,8 @@
     component.mainMethodName ??= mainMethod;
 
     _byteOffset = _componentStartOffset + componentFileSize;
+
+    assert(typeParameterStack.isEmpty);
   }
 
   /// Read a list of strings. If the list is empty, [null] is returned.
@@ -1016,7 +1030,9 @@
     }
     bool shouldWriteData = node == null || _isReadingLibraryImplementation;
     if (node == null) {
-      node = new Class(reference: reference)..level = ClassLevel.Temporary;
+      node = new Class(reference: reference)
+        ..level = ClassLevel.Temporary
+        ..dirty = false;
     }
 
     var fileUri = readUriReference();
@@ -1036,6 +1052,9 @@
       debugPath.add(node.name ?? 'normal-class');
       return true;
     }());
+
+    assert(typeParameterStack.length == 0);
+
     readAndPushTypeParameterList(node.typeParameters, node);
     var supertype = readSupertypeOption();
     var mixedInType = readSupertypeOption();
@@ -1044,16 +1063,12 @@
     } else {
       _skipNodeList(readSupertype);
     }
-    _mergeNamedNodeList(node.fields, (index) => readField(), node);
-    _mergeNamedNodeList(node.constructors, (index) => readConstructor(), node);
+    if (_disableLazyClassReading) {
+      readClassPartialContent(node, procedureOffsets);
+    } else {
+      _setLazyLoadClass(node, procedureOffsets);
+    }
 
-    _mergeNamedNodeList(node.procedures, (index) {
-      _byteOffset = procedureOffsets[index];
-      return readProcedure(procedureOffsets[index + 1]);
-    }, node);
-    _byteOffset = procedureOffsets.last;
-    _mergeNamedNodeList(node.redirectingFactoryConstructors,
-        (index) => readRedirectingFactoryConstructor(), node);
     typeParameterStack.length = 0;
     assert(debugPath.removeLast() != null);
     if (shouldWriteData) {
@@ -1120,6 +1135,39 @@
     return node;
   }
 
+  /// Reads the partial content of a class, namely fields, procedures,
+  /// constructors and redirecting factory constructors.
+  void readClassPartialContent(Class node, List<int> procedureOffsets) {
+    _mergeNamedNodeList(node.fieldsInternal, (index) => readField(), node);
+    _mergeNamedNodeList(
+        node.constructorsInternal, (index) => readConstructor(), node);
+
+    _mergeNamedNodeList(node.proceduresInternal, (index) {
+      _byteOffset = procedureOffsets[index];
+      return readProcedure(procedureOffsets[index + 1]);
+    }, node);
+    _byteOffset = procedureOffsets.last;
+    _mergeNamedNodeList(node.redirectingFactoryConstructorsInternal,
+        (index) => readRedirectingFactoryConstructor(), node);
+  }
+
+  /// Set the lazyBuilder on the class so it can be lazy loaded in the future.
+  void _setLazyLoadClass(Class node, List<int> procedureOffsets) {
+    final int savedByteOffset = _byteOffset;
+    final int componentStartOffset = _componentStartOffset;
+    final Library currentLibrary = _currentLibrary;
+    node.lazyBuilder = () {
+      _byteOffset = savedByteOffset;
+      _currentLibrary = currentLibrary;
+      assert(typeParameterStack.isEmpty);
+      _componentStartOffset = componentStartOffset;
+      typeParameterStack.addAll(node.typeParameters);
+
+      readClassPartialContent(node, procedureOffsets);
+      typeParameterStack.length = 0;
+    };
+  }
+
   int getAndResetTransformerFlags() {
     int flags = _transformerFlags;
     _transformerFlags = 0;
@@ -1416,8 +1464,7 @@
       ..fileEndOffset = endOffset;
 
     if (lazyLoadBody) {
-      _setLazyLoadFunction(result, oldLabelStackBase, variableStackHeight,
-          typeParameterStackHeight);
+      _setLazyLoadFunction(result, oldLabelStackBase, variableStackHeight);
     }
 
     labelStackBase = oldLabelStackBase;
@@ -1427,8 +1474,8 @@
     return result;
   }
 
-  void _setLazyLoadFunction(FunctionNode result, int oldLabelStackBase,
-      int variableStackHeight, int typeParameterStackHeight) {
+  void _setLazyLoadFunction(
+      FunctionNode result, int oldLabelStackBase, int variableStackHeight) {
     final int savedByteOffset = _byteOffset;
     final int componentStartOffset = _componentStartOffset;
     final List<TypeParameter> typeParameters = typeParameterStack.toList();
@@ -1447,7 +1494,7 @@
       result.body?.parent = result;
       labelStackBase = oldLabelStackBase;
       variableStack.length = variableStackHeight;
-      typeParameterStack.length = typeParameterStackHeight;
+      typeParameterStack.clear();
       if (result.parent is Procedure) {
         Procedure parent = result.parent;
         parent.transformerFlags |= getAndResetTransformerFlags();
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index dc93073..0645cb9 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -146,7 +146,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 = 31;
+  static const int BinaryFormatVersion = 32;
 }
 
 abstract class ConstantTag {
diff --git a/pkg/kernel/lib/canonical_name.dart b/pkg/kernel/lib/canonical_name.dart
index 29aeac4..71a42bf 100644
--- a/pkg/kernel/lib/canonical_name.dart
+++ b/pkg/kernel/lib/canonical_name.dart
@@ -179,6 +179,12 @@
   void unbind() {
     if (reference == null) return;
     assert(reference.canonicalName == this);
+    if (reference.node is Class) {
+      // TODO(jensj): Get rid of this. This is only needed because pkg:vm does
+      // weird stuff in transformations. `unbind` should probably be private.
+      Class c = reference.node;
+      c.ensureLoaded();
+    }
     reference.canonicalName = null;
     reference = null;
   }
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index 73cd12a..b2431be 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -8,6 +8,7 @@
 import 'dart:typed_data';
 
 import 'ast.dart';
+import 'core_types.dart';
 import 'src/heap.dart';
 import 'type_algebra.dart';
 
@@ -62,7 +63,7 @@
   /// one type is a subtype of the other, or where both types are based on the
   /// same class.
   InterfaceType getLegacyLeastUpperBound(
-      InterfaceType type1, InterfaceType type2);
+      InterfaceType type1, InterfaceType type2, CoreTypes coreTypes);
 
   /// Returns the instantiation of [superclass] that is implemented by [class_],
   /// or `null` if [class_] does not implement [superclass] at all.
@@ -540,7 +541,7 @@
 
   @override
   InterfaceType getLegacyLeastUpperBound(
-      InterfaceType type1, InterfaceType type2) {
+      InterfaceType type1, InterfaceType type2, CoreTypes coreTypes) {
     // The algorithm is: first we compute a list of superclasses for both types,
     // ordered from greatest to least depth, and ordered by topological sort
     // index within each depth.  Due to the sort order, we can find the
@@ -614,7 +615,8 @@
       //   immediately.  Since all interface types are subtypes of Object, this
       //   ensures the loop terminates.
       if (next.classNode.typeParameters.isEmpty) {
-        candidate = next.classNode.rawType;
+        // TODO(dmitryas): Update nullability as necessary for the LUB spec.
+        candidate = coreTypes.legacyRawType(next.classNode);
         if (currentDepth == 0) return candidate;
         ++numCandidatesAtThisDepth;
       } else {
@@ -660,16 +662,14 @@
 
   @override
   Member getDispatchTarget(Class class_, Name name, {bool setter: false}) {
-    _ClassInfo info = infoFor(class_);
     List<Member> list =
-        setter ? info.implementedSetters : info.implementedGettersAndCalls;
+        _buildImplementedMembers(class_, infoFor(class_), setters: setter);
     return ClassHierarchy.findMemberByName(list, name);
   }
 
   @override
   List<Member> getDispatchTargets(Class class_, {bool setters: false}) {
-    _ClassInfo info = infoFor(class_);
-    return setters ? info.implementedSetters : info.implementedGettersAndCalls;
+    return _buildImplementedMembers(class_, infoFor(class_), setters: setters);
   }
 
   @override
@@ -685,8 +685,7 @@
 
   @override
   List<Member> getDeclaredMembers(Class class_, {bool setters: false}) {
-    var info = infoFor(class_);
-    return setters ? info.declaredSetters : info.declaredGettersAndCalls;
+    return _buildDeclaredMembers(class_, infoFor(class_), setters: setters);
   }
 
   @override
@@ -698,8 +697,10 @@
       var superclass = supertype.classNode;
       var superGetters = getInterfaceMembers(superclass);
       var superSetters = getInterfaceMembers(superclass, setters: true);
-      _reportOverrides(info.declaredGettersAndCalls, superGetters, callback);
-      _reportOverrides(info.declaredSetters, superSetters, callback,
+      _reportOverrides(_buildDeclaredMembers(class_, info, setters: false),
+          superGetters, callback);
+      _reportOverrides(_buildDeclaredMembers(class_, info, setters: true),
+          superSetters, callback,
           isSetter: true);
     }
   }
@@ -835,13 +836,12 @@
     });
 
     for (_ClassInfo info in infos) {
-      Class class_ = info.classNode;
-      _buildDeclaredMembers(class_, info);
-      _buildImplementedMembers(class_, info);
-      info.interfaceSetters = null;
-      info.interfaceGettersAndCalls = null;
-      _buildInterfaceMembers(class_, info, setters: true);
-      _buildInterfaceMembers(class_, info, setters: false);
+      info.lazyDeclaredGettersAndCalls = null;
+      info.lazyDeclaredSetters = null;
+      info.lazyImplementedGettersAndCalls = null;
+      info.lazyImplementedSetters = null;
+      info.lazyInterfaceGettersAndCalls = null;
+      info.lazyInterfaceSetters = null;
     }
 
     assert(sanityCheckAlsoKnowsParentAndLibrary());
@@ -921,9 +921,6 @@
         _recordSuperTypes(info, supertype);
       }
 
-      _buildInterfaceMembers(class_, info, setters: true);
-      _buildInterfaceMembers(class_, info, setters: false);
-
       if (info == null) {
         throw "No info for ${class_.name} from ${class_.fileUri}.";
       }
@@ -973,8 +970,7 @@
           _topologicalSortVisit(supertype.classNode, beingVisited,
               orderedList: orderedList));
     }
-    _buildDeclaredMembers(classNode, info);
-    _buildImplementedMembers(classNode, info);
+
     info.topologicalIndex = _topSortIndex++;
 
     _infoMap[classNode] = info;
@@ -983,71 +979,92 @@
     return info.depth = superDepth + 1;
   }
 
-  void _buildDeclaredMembers(Class classNode, _ClassInfo info) {
-    if (classNode.mixedInType != null) {
-      _ClassInfo mixedInfo = _infoMap[classNode.mixedInType.classNode];
+  List<Member> _buildImplementedMembers(Class classNode, _ClassInfo info,
+      {bool setters}) {
+    if (info == null) {
+      throw "${classNode.fileUri}: No class info for ${classNode.name}";
+    }
+    List<Member> members = setters
+        ? info.lazyImplementedSetters
+        : info.lazyImplementedGettersAndCalls;
+    if (members != null) return members;
 
-      List<Member> declaredGettersAndCalls = <Member>[];
-      for (Member mixinMember in mixedInfo.declaredGettersAndCalls) {
-        if (mixinMember is! Procedure ||
-            (mixinMember is Procedure &&
-                !mixinMember.isNoSuchMethodForwarder)) {
-          declaredGettersAndCalls.add(mixinMember);
-        }
-      }
-
-      List<Member> declaredSetters = <Member>[];
-      for (Member mixinMember in mixedInfo.declaredSetters) {
-        if (mixinMember is! Procedure ||
-            (mixinMember is Procedure &&
-                !mixinMember.isNoSuchMethodForwarder)) {
-          declaredSetters.add(mixinMember);
-        }
-      }
-
-      info.declaredGettersAndCalls = declaredGettersAndCalls;
-      info.declaredSetters = declaredSetters;
+    List<Member> inherited;
+    if (classNode.supertype == null) {
+      inherited = const <Member>[];
     } else {
-      var members = info.declaredGettersAndCalls = <Member>[];
-      var setters = info.declaredSetters = <Member>[];
+      Class superClassNode = classNode.supertype.classNode;
+      _ClassInfo superInfo = _infoMap[superClassNode];
+      inherited =
+          _buildImplementedMembers(superClassNode, superInfo, setters: setters);
+    }
+    members = _inheritMembers(
+        _buildDeclaredMembers(classNode, info, setters: setters), inherited,
+        skipAbstractMembers: true);
+    if (setters) {
+      info.lazyImplementedSetters = members;
+    } else {
+      info.lazyImplementedGettersAndCalls = members;
+    }
+    return members;
+  }
+
+  List<Member> _buildDeclaredMembers(Class classNode, _ClassInfo info,
+      {bool setters}) {
+    if (info == null) {
+      throw "${classNode.fileUri}: No class info for ${classNode.name}";
+    }
+    List<Member> members =
+        setters ? info.lazyDeclaredSetters : info.lazyDeclaredGettersAndCalls;
+    if (members != null) return members;
+
+    if (classNode.mixedInType != null) {
+      Class mixedInClassNode = classNode.mixedInType.classNode;
+      _ClassInfo mixedInInfo = _infoMap[mixedInClassNode];
+
+      members = <Member>[];
+      for (Member mixinMember in _buildDeclaredMembers(
+          mixedInClassNode, mixedInInfo,
+          setters: setters)) {
+        if (mixinMember is! Procedure ||
+            (mixinMember is Procedure &&
+                !mixinMember.isNoSuchMethodForwarder)) {
+          members.add(mixinMember);
+        }
+      }
+    } else {
+      members = new List<Member>();
       for (Procedure procedure in classNode.procedures) {
         if (procedure.isStatic) continue;
         if (procedure.kind == ProcedureKind.Setter) {
-          setters.add(procedure);
+          if (setters) {
+            members.add(procedure);
+          }
         } else {
-          members.add(procedure);
+          if (!setters) {
+            members.add(procedure);
+          }
         }
       }
       for (Field field in classNode.fields) {
         if (field.isStatic) continue;
-        if (field.hasImplicitGetter) {
+        if (!setters && field.hasImplicitGetter) {
           members.add(field);
         }
-        if (field.hasImplicitSetter) {
-          setters.add(field);
+        if (setters && field.hasImplicitSetter) {
+          members.add(field);
         }
       }
-      members.sort(ClassHierarchy.compareMembers);
-      setters.sort(ClassHierarchy.compareMembers);
-    }
-  }
 
-  void _buildImplementedMembers(Class classNode, _ClassInfo info) {
-    List<Member> inheritedMembers;
-    List<Member> inheritedSetters;
-    if (classNode.supertype == null) {
-      inheritedMembers = inheritedSetters = const <Member>[];
-    } else {
-      _ClassInfo superInfo = _infoMap[classNode.supertype.classNode];
-      inheritedMembers = superInfo.implementedGettersAndCalls;
-      inheritedSetters = superInfo.implementedSetters;
+      members.sort(ClassHierarchy.compareMembers);
     }
-    info.implementedGettersAndCalls = _inheritMembers(
-        info.declaredGettersAndCalls, inheritedMembers,
-        skipAbstractMembers: true);
-    info.implementedSetters = _inheritMembers(
-        info.declaredSetters, inheritedSetters,
-        skipAbstractMembers: true);
+
+    if (setters) {
+      info.lazyDeclaredSetters = members;
+    } else {
+      info.lazyDeclaredGettersAndCalls = members;
+    }
+    return members;
   }
 
   List<Member> _buildInterfaceMembers(Class classNode, _ClassInfo info,
@@ -1056,11 +1073,12 @@
       throw "${classNode.fileUri}: No class info for ${classNode.name}";
     }
     List<Member> members =
-        setters ? info.interfaceSetters : info.interfaceGettersAndCalls;
+        setters ? info.lazyInterfaceSetters : info.lazyInterfaceGettersAndCalls;
     if (members != null) return members;
     List<Member> allInheritedMembers = <Member>[];
     List<Member> declared =
-        setters ? info.declaredSetters : info.declaredGettersAndCalls;
+        _buildDeclaredMembers(classNode, info, setters: setters);
+
     void inheritFrom(Supertype type) {
       if (type == null) return;
       List<Member> inherited = _buildInterfaceMembers(
@@ -1076,9 +1094,9 @@
     classNode.implementedTypes.forEach(inheritFrom);
     members = _inheritMembers(declared, allInheritedMembers);
     if (setters) {
-      info.interfaceSetters = members;
+      info.lazyInterfaceSetters = members;
     } else {
-      info.interfaceGettersAndCalls = members;
+      info.lazyInterfaceGettersAndCalls = members;
     }
     return members;
   }
@@ -1399,22 +1417,22 @@
 
   /// Instance fields, getters, methods, and operators declared in this class
   /// or its mixed-in class, sorted according to [_compareMembers].
-  List<Member> declaredGettersAndCalls;
+  List<Member> lazyDeclaredGettersAndCalls;
 
   /// Non-final instance fields and setters declared in this class or its
   /// mixed-in class, sorted according to [_compareMembers].
-  List<Member> declaredSetters;
+  List<Member> lazyDeclaredSetters;
 
   /// Instance fields, getters, methods, and operators implemented by this class
   /// (declared or inherited).
-  List<Member> implementedGettersAndCalls;
+  List<Member> lazyImplementedGettersAndCalls;
 
   /// Non-final instance fields and setters implemented by this class
   /// (declared or inherited).
-  List<Member> implementedSetters;
+  List<Member> lazyImplementedSetters;
 
-  List<Member> interfaceGettersAndCalls;
-  List<Member> interfaceSetters;
+  List<Member> lazyInterfaceGettersAndCalls;
+  List<Member> lazyInterfaceSetters;
 
   _ClassInfo(this.classNode);
 
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index e0dc4e7..f80716e 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -494,6 +494,7 @@
   }
 
   visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+    prepareTypeParameters(node.typeParameters);
     return new RedirectingFactoryConstructor(node.targetReference,
         name: node.name,
         isConst: node.isConst,
@@ -510,12 +511,19 @@
           : const <Expression>[];
   }
 
+  void prepareTypeParameters(List<TypeParameter> typeParameters) {
+    for (TypeParameter node in typeParameters) {
+      TypeParameter newNode = typeParams[node];
+      if (newNode == null) {
+        newNode = new TypeParameter(node.name);
+        typeParams[node] = newNode;
+        typeSubstitution[node] = new TypeParameterType(newNode);
+      }
+    }
+  }
+
   visitTypeParameter(TypeParameter node) {
     TypeParameter newNode = typeParams[node];
-    if (newNode == null) {
-      newNode = new TypeParameter(node.name);
-      typeSubstitution[node] = new TypeParameterType(newNode);
-    }
     newNode.bound = visitType(node.bound);
     if (node.defaultType != null) {
       newNode.defaultType = visitType(node.defaultType);
@@ -538,6 +546,7 @@
   }
 
   visitFunctionNode(FunctionNode node) {
+    prepareTypeParameters(node.typeParameters);
     var typeParameters = node.typeParameters.map(clone).toList();
     var positional = node.positionalParameters.map(clone).toList();
     var named = node.namedParameters.map(clone).toList();
diff --git a/pkg/kernel/lib/core_types.dart b/pkg/kernel/lib/core_types.dart
index aa8d0f7..9e3dea1 100644
--- a/pkg/kernel/lib/core_types.dart
+++ b/pkg/kernel/lib/core_types.dart
@@ -95,6 +95,80 @@
   Field _pragmaOptions;
   Constructor _pragmaConstructor;
 
+  InterfaceType _objectLegacyRawType;
+  InterfaceType _objectNullableRawType;
+  InterfaceType _objectNonNullableRawType;
+  InterfaceType _nullType;
+  InterfaceType _boolLegacyRawType;
+  InterfaceType _boolNullableRawType;
+  InterfaceType _boolNonNullableRawType;
+  InterfaceType _intLegacyRawType;
+  InterfaceType _intNullableRawType;
+  InterfaceType _intNonNullableRawType;
+  InterfaceType _numLegacyRawType;
+  InterfaceType _numNullableRawType;
+  InterfaceType _numNonNullableRawType;
+  InterfaceType _doubleLegacyRawType;
+  InterfaceType _doubleNullableRawType;
+  InterfaceType _doubleNonNullableRawType;
+  InterfaceType _stringLegacyRawType;
+  InterfaceType _stringNullableRawType;
+  InterfaceType _stringNonNullableRawType;
+  InterfaceType _listLegacyRawType;
+  InterfaceType _listNullableRawType;
+  InterfaceType _listNonNullableRawType;
+  InterfaceType _setLegacyRawType;
+  InterfaceType _setNullableRawType;
+  InterfaceType _setNonNullableRawType;
+  InterfaceType _mapLegacyRawType;
+  InterfaceType _mapNullableRawType;
+  InterfaceType _mapNonNullableRawType;
+  InterfaceType _iterableLegacyRawType;
+  InterfaceType _iterableNullableRawType;
+  InterfaceType _iterableNonNullableRawType;
+  InterfaceType _iteratorLegacyRawType;
+  InterfaceType _iteratorNullableRawType;
+  InterfaceType _iteratorNonNullableRawType;
+  InterfaceType _symbolLegacyRawType;
+  InterfaceType _symbolNullableRawType;
+  InterfaceType _symbolNonNullableRawType;
+  InterfaceType _typeLegacyRawType;
+  InterfaceType _typeNullableRawType;
+  InterfaceType _typeNonNullableRawType;
+  InterfaceType _functionLegacyRawType;
+  InterfaceType _functionNullableRawType;
+  InterfaceType _functionNonNullableRawType;
+  InterfaceType _invocationLegacyRawType;
+  InterfaceType _invocationNullableRawType;
+  InterfaceType _invocationNonNullableRawType;
+  InterfaceType _invocationMirrorLegacyRawType;
+  InterfaceType _invocationMirrorNullableRawType;
+  InterfaceType _invocationMirrorNonNullableRawType;
+  InterfaceType _futureLegacyRawType;
+  InterfaceType _futureNullableRawType;
+  InterfaceType _futureNonNullableRawType;
+  InterfaceType _stackTraceLegacyRawType;
+  InterfaceType _stackTraceNullableRawType;
+  InterfaceType _stackTraceNonNullableRawType;
+  InterfaceType _streamLegacyRawType;
+  InterfaceType _streamNullableRawType;
+  InterfaceType _streamNonNullableRawType;
+  InterfaceType _asyncAwaitCompleterLegacyRawType;
+  InterfaceType _asyncAwaitCompleterNullableRawType;
+  InterfaceType _asyncAwaitCompleterNonNullableRawType;
+  InterfaceType _futureOrLegacyRawType;
+  InterfaceType _futureOrNullableRawType;
+  InterfaceType _futureOrNonNullableRawType;
+  InterfaceType _pragmaLegacyRawType;
+  InterfaceType _pragmaNullableRawType;
+  InterfaceType _pragmaNonNullableRawType;
+  final Map<Class, InterfaceType> _legacyRawTypes =
+      new Map<Class, InterfaceType>.identity();
+  final Map<Class, InterfaceType> _nullableRawTypes =
+      new Map<Class, InterfaceType>.identity();
+  final Map<Class, InterfaceType> _nonNullableRawTypes =
+      new Map<Class, InterfaceType>.identity();
+
   CoreTypes(Component component)
       : index = new LibraryIndex.coreLibraries(component);
 
@@ -388,4 +462,777 @@
     return _boolFromEnvironment ??=
         index.getMember('dart:core', 'bool', 'fromEnvironment');
   }
+
+  InterfaceType get objectLegacyRawType {
+    return _objectLegacyRawType ??= _legacyRawTypes[objectClass] ??=
+        new InterfaceType(objectClass, const <DartType>[], Nullability.legacy);
+  }
+
+  InterfaceType get objectNullableRawType {
+    return _objectNullableRawType ??= _nullableRawTypes[objectClass] ??=
+        new InterfaceType(
+            objectClass, const <DartType>[], Nullability.nullable);
+  }
+
+  InterfaceType get objectNonNullableRawType {
+    return _objectNonNullableRawType ??= _nonNullableRawTypes[objectClass] ??=
+        new InterfaceType(
+            objectClass, const <DartType>[], Nullability.nonNullable);
+  }
+
+  InterfaceType objectRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return objectLegacyRawType;
+      case Nullability.nullable:
+        return objectNullableRawType;
+      case Nullability.nonNullable:
+        return objectNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  /// Null is always nullable, so there's only one raw type for that class.
+  InterfaceType get nullType {
+    return _nullType ??= _nullableRawTypes[nullClass] ??=
+        new InterfaceType(nullClass, const <DartType>[], Nullability.nullable);
+  }
+
+  InterfaceType get boolLegacyRawType {
+    return _boolLegacyRawType ??= _legacyRawTypes[boolClass] ??=
+        new InterfaceType(boolClass, const <DartType>[], Nullability.legacy);
+  }
+
+  InterfaceType get boolNullableRawType {
+    return _boolNullableRawType ??= _nullableRawTypes[boolClass] ??=
+        new InterfaceType(boolClass, const <DartType>[], Nullability.nullable);
+  }
+
+  InterfaceType get boolNonNullableRawType {
+    return _boolNonNullableRawType ??= _nonNullableRawTypes[boolClass] ??=
+        new InterfaceType(
+            boolClass, const <DartType>[], Nullability.nonNullable);
+  }
+
+  InterfaceType boolRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return boolLegacyRawType;
+      case Nullability.nullable:
+        return boolNullableRawType;
+      case Nullability.nonNullable:
+        return boolNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get intLegacyRawType {
+    return _intLegacyRawType ??= _legacyRawTypes[intClass] ??=
+        new InterfaceType(intClass, const <DartType>[], Nullability.legacy);
+  }
+
+  InterfaceType get intNullableRawType {
+    return _intNullableRawType ??= _nullableRawTypes[intClass] ??=
+        new InterfaceType(intClass, const <DartType>[], Nullability.nullable);
+  }
+
+  InterfaceType get intNonNullableRawType {
+    return _intNonNullableRawType ??= _nonNullableRawTypes[intClass] ??=
+        new InterfaceType(
+            intClass, const <DartType>[], Nullability.nonNullable);
+  }
+
+  InterfaceType intRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return intLegacyRawType;
+      case Nullability.nullable:
+        return intNullableRawType;
+      case Nullability.nonNullable:
+        return intNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get numLegacyRawType {
+    return _numLegacyRawType ??= _legacyRawTypes[numClass] ??=
+        new InterfaceType(numClass, const <DartType>[], Nullability.legacy);
+  }
+
+  InterfaceType get numNullableRawType {
+    return _numNullableRawType ??= _nullableRawTypes[numClass] ??=
+        new InterfaceType(numClass, const <DartType>[], Nullability.nullable);
+  }
+
+  InterfaceType get numNonNullableRawType {
+    return _numNonNullableRawType ??= _nonNullableRawTypes[numClass] ??=
+        new InterfaceType(
+            numClass, const <DartType>[], Nullability.nonNullable);
+  }
+
+  InterfaceType numRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return numLegacyRawType;
+      case Nullability.nullable:
+        return numNullableRawType;
+      case Nullability.nonNullable:
+        return numNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get doubleLegacyRawType {
+    return _doubleLegacyRawType ??= _legacyRawTypes[doubleClass] ??=
+        new InterfaceType(doubleClass, const <DartType>[], Nullability.legacy);
+  }
+
+  InterfaceType get doubleNullableRawType {
+    return _doubleNullableRawType ??= _nullableRawTypes[doubleClass] ??=
+        new InterfaceType(
+            doubleClass, const <DartType>[], Nullability.nullable);
+  }
+
+  InterfaceType get doubleNonNullableRawType {
+    return _doubleNonNullableRawType ??= _nonNullableRawTypes[doubleClass] ??=
+        new InterfaceType(
+            doubleClass, const <DartType>[], Nullability.nonNullable);
+  }
+
+  InterfaceType doubleRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return doubleLegacyRawType;
+      case Nullability.nullable:
+        return doubleNullableRawType;
+      case Nullability.nonNullable:
+        return doubleNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get stringLegacyRawType {
+    return _stringLegacyRawType ??= _legacyRawTypes[stringClass] ??=
+        new InterfaceType(stringClass, const <DartType>[], Nullability.legacy);
+  }
+
+  InterfaceType get stringNullableRawType {
+    return _stringNullableRawType ??= _nullableRawTypes[stringClass] ??=
+        new InterfaceType(
+            stringClass, const <DartType>[], Nullability.nullable);
+  }
+
+  InterfaceType get stringNonNullableRawType {
+    return _stringNonNullableRawType ??= _nonNullableRawTypes[stringClass] ??=
+        new InterfaceType(
+            stringClass, const <DartType>[], Nullability.nonNullable);
+  }
+
+  InterfaceType stringRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return stringLegacyRawType;
+      case Nullability.nullable:
+        return stringNullableRawType;
+      case Nullability.nonNullable:
+        return stringNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get listLegacyRawType {
+    return _listLegacyRawType ??= _legacyRawTypes[listClass] ??=
+        new InterfaceType(listClass, const <DartType>[const DynamicType()],
+            Nullability.legacy);
+  }
+
+  InterfaceType get listNullableRawType {
+    return _listNullableRawType ??= _nullableRawTypes[listClass] ??=
+        new InterfaceType(listClass, const <DartType>[const DynamicType()],
+            Nullability.nullable);
+  }
+
+  InterfaceType get listNonNullableRawType {
+    return _listNonNullableRawType ??= _nonNullableRawTypes[listClass] ??=
+        new InterfaceType(listClass, const <DartType>[const DynamicType()],
+            Nullability.nonNullable);
+  }
+
+  InterfaceType listRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return listLegacyRawType;
+      case Nullability.nullable:
+        return listNullableRawType;
+      case Nullability.nonNullable:
+        return listNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get setLegacyRawType {
+    return _setLegacyRawType ??= _legacyRawTypes[setClass] ??=
+        new InterfaceType(setClass, const <DartType>[const DynamicType()],
+            Nullability.legacy);
+  }
+
+  InterfaceType get setNullableRawType {
+    return _setNullableRawType ??= _nullableRawTypes[setClass] ??=
+        new InterfaceType(setClass, const <DartType>[const DynamicType()],
+            Nullability.nullable);
+  }
+
+  InterfaceType get setNonNullableRawType {
+    return _setNonNullableRawType ??= _nonNullableRawTypes[setClass] ??=
+        new InterfaceType(setClass, const <DartType>[const DynamicType()],
+            Nullability.nonNullable);
+  }
+
+  InterfaceType setRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return setLegacyRawType;
+      case Nullability.nullable:
+        return setNullableRawType;
+      case Nullability.nonNullable:
+        return setNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get mapLegacyRawType {
+    return _mapLegacyRawType ??= _legacyRawTypes[mapClass] ??=
+        new InterfaceType(
+            mapClass,
+            const <DartType>[const DynamicType(), const DynamicType()],
+            Nullability.legacy);
+  }
+
+  InterfaceType get mapNullableRawType {
+    return _mapNullableRawType ??= _nullableRawTypes[mapClass] ??=
+        new InterfaceType(
+            mapClass,
+            const <DartType>[const DynamicType(), const DynamicType()],
+            Nullability.nullable);
+  }
+
+  InterfaceType get mapNonNullableRawType {
+    return _mapNonNullableRawType ??= _nonNullableRawTypes[mapClass] ??=
+        new InterfaceType(
+            mapClass,
+            const <DartType>[const DynamicType(), const DynamicType()],
+            Nullability.nonNullable);
+  }
+
+  InterfaceType mapRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return mapLegacyRawType;
+      case Nullability.nullable:
+        return mapNullableRawType;
+      case Nullability.nonNullable:
+        return mapNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get iterableLegacyRawType {
+    return _iterableLegacyRawType ??= _legacyRawTypes[iterableClass] ??=
+        new InterfaceType(iterableClass, const <DartType>[const DynamicType()],
+            Nullability.legacy);
+  }
+
+  InterfaceType get iterableNullableRawType {
+    return _iterableNullableRawType ??= _nullableRawTypes[iterableClass] ??=
+        new InterfaceType(iterableClass, const <DartType>[const DynamicType()],
+            Nullability.nullable);
+  }
+
+  InterfaceType get iterableNonNullableRawType {
+    return _iterableNonNullableRawType ??=
+        _nonNullableRawTypes[iterableClass] ??= new InterfaceType(iterableClass,
+            const <DartType>[const DynamicType()], Nullability.nonNullable);
+  }
+
+  InterfaceType iterableRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return iterableLegacyRawType;
+      case Nullability.nullable:
+        return iterableNullableRawType;
+      case Nullability.nonNullable:
+        return iterableNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get iteratorLegacyRawType {
+    return _iteratorLegacyRawType ??= _legacyRawTypes[iteratorClass] ??=
+        new InterfaceType(iteratorClass, const <DartType>[const DynamicType()],
+            Nullability.legacy);
+  }
+
+  InterfaceType get iteratorNullableRawType {
+    return _iteratorNullableRawType ??= _nullableRawTypes[iteratorClass] ??=
+        new InterfaceType(iteratorClass, const <DartType>[const DynamicType()],
+            Nullability.nullable);
+  }
+
+  InterfaceType get iteratorNonNullableRawType {
+    return _iteratorNonNullableRawType ??=
+        _nonNullableRawTypes[iteratorClass] ??= new InterfaceType(iteratorClass,
+            const <DartType>[const DynamicType()], Nullability.nonNullable);
+  }
+
+  InterfaceType iteratorRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return iteratorLegacyRawType;
+      case Nullability.nullable:
+        return iteratorNullableRawType;
+      case Nullability.nonNullable:
+        return iteratorNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get symbolLegacyRawType {
+    return _symbolLegacyRawType ??= _legacyRawTypes[symbolClass] ??=
+        new InterfaceType(symbolClass, const <DartType>[], Nullability.legacy);
+  }
+
+  InterfaceType get symbolNullableRawType {
+    return _symbolNullableRawType ??= _nullableRawTypes[symbolClass] ??=
+        new InterfaceType(
+            symbolClass, const <DartType>[], Nullability.nullable);
+  }
+
+  InterfaceType get symbolNonNullableRawType {
+    return _symbolNonNullableRawType ??= _nonNullableRawTypes[symbolClass] ??=
+        new InterfaceType(
+            symbolClass, const <DartType>[], Nullability.nonNullable);
+  }
+
+  InterfaceType symbolRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return symbolLegacyRawType;
+      case Nullability.nullable:
+        return symbolNullableRawType;
+      case Nullability.nonNullable:
+        return symbolNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get typeLegacyRawType {
+    return _typeLegacyRawType ??= _legacyRawTypes[typeClass] ??=
+        new InterfaceType(typeClass, const <DartType>[], Nullability.legacy);
+  }
+
+  InterfaceType get typeNullableRawType {
+    return _typeNullableRawType ??= _nullableRawTypes[typeClass] ??=
+        new InterfaceType(typeClass, const <DartType>[], Nullability.nullable);
+  }
+
+  InterfaceType get typeNonNullableRawType {
+    return _typeNonNullableRawType ??= _nonNullableRawTypes[typeClass] ??=
+        new InterfaceType(
+            typeClass, const <DartType>[], Nullability.nonNullable);
+  }
+
+  InterfaceType typeRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return typeLegacyRawType;
+      case Nullability.nullable:
+        return typeNullableRawType;
+      case Nullability.nonNullable:
+        return typeNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get functionLegacyRawType {
+    return _functionLegacyRawType ??= _legacyRawTypes[functionClass] ??=
+        new InterfaceType(
+            functionClass, const <DartType>[], Nullability.legacy);
+  }
+
+  InterfaceType get functionNullableRawType {
+    return _functionNullableRawType ??= _nullableRawTypes[functionClass] ??=
+        new InterfaceType(
+            functionClass, const <DartType>[], Nullability.nullable);
+  }
+
+  InterfaceType get functionNonNullableRawType {
+    return _functionNonNullableRawType ??=
+        _nonNullableRawTypes[functionClass] ??= new InterfaceType(
+            functionClass, const <DartType>[], Nullability.nonNullable);
+  }
+
+  InterfaceType functionRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return functionLegacyRawType;
+      case Nullability.nullable:
+        return functionNullableRawType;
+      case Nullability.nonNullable:
+        return functionNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get invocationLegacyRawType {
+    return _invocationLegacyRawType ??= _legacyRawTypes[invocationClass] ??=
+        new InterfaceType(
+            invocationClass, const <DartType>[], Nullability.legacy);
+  }
+
+  InterfaceType get invocationNullableRawType {
+    return _invocationNullableRawType ??= _nullableRawTypes[invocationClass] ??=
+        new InterfaceType(
+            invocationClass, const <DartType>[], Nullability.nullable);
+  }
+
+  InterfaceType get invocationNonNullableRawType {
+    return _invocationNonNullableRawType ??=
+        _nonNullableRawTypes[invocationClass] ??= new InterfaceType(
+            invocationClass, const <DartType>[], Nullability.nonNullable);
+  }
+
+  InterfaceType invocationRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return invocationLegacyRawType;
+      case Nullability.nullable:
+        return invocationNullableRawType;
+      case Nullability.nonNullable:
+        return invocationNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get invocationMirrorLegacyRawType {
+    return _invocationMirrorLegacyRawType ??=
+        _legacyRawTypes[invocationMirrorClass] ??= new InterfaceType(
+            invocationMirrorClass, const <DartType>[], Nullability.legacy);
+  }
+
+  InterfaceType get invocationMirrorNullableRawType {
+    return _invocationMirrorNullableRawType ??=
+        _nullableRawTypes[invocationMirrorClass] ??= new InterfaceType(
+            invocationMirrorClass, const <DartType>[], Nullability.nullable);
+  }
+
+  InterfaceType get invocationMirrorNonNullableRawType {
+    return _invocationMirrorNonNullableRawType ??=
+        _nonNullableRawTypes[invocationMirrorClass] ??= new InterfaceType(
+            invocationMirrorClass, const <DartType>[], Nullability.nonNullable);
+  }
+
+  InterfaceType invocationMirrorRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return invocationMirrorLegacyRawType;
+      case Nullability.nullable:
+        return invocationMirrorNullableRawType;
+      case Nullability.nonNullable:
+        return invocationMirrorNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get futureLegacyRawType {
+    return _futureLegacyRawType ??= _legacyRawTypes[futureClass] ??=
+        new InterfaceType(futureClass, const <DartType>[const DynamicType()],
+            Nullability.legacy);
+  }
+
+  InterfaceType get futureNullableRawType {
+    return _futureNullableRawType ??= _nullableRawTypes[futureClass] ??=
+        new InterfaceType(futureClass, const <DartType>[const DynamicType()],
+            Nullability.nullable);
+  }
+
+  InterfaceType get futureNonNullableRawType {
+    return _futureNonNullableRawType ??= _nonNullableRawTypes[futureClass] ??=
+        new InterfaceType(futureClass, const <DartType>[const DynamicType()],
+            Nullability.nonNullable);
+  }
+
+  InterfaceType futureRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return futureLegacyRawType;
+      case Nullability.nullable:
+        return futureNullableRawType;
+      case Nullability.nonNullable:
+        return futureNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get stackTraceLegacyRawType {
+    return _stackTraceLegacyRawType ??= _legacyRawTypes[stackTraceClass] ??=
+        new InterfaceType(
+            stackTraceClass, const <DartType>[], Nullability.legacy);
+  }
+
+  InterfaceType get stackTraceNullableRawType {
+    return _stackTraceNullableRawType ??= _nullableRawTypes[stackTraceClass] ??=
+        new InterfaceType(
+            stackTraceClass, const <DartType>[], Nullability.nullable);
+  }
+
+  InterfaceType get stackTraceNonNullableRawType {
+    return _stackTraceNonNullableRawType ??=
+        _nonNullableRawTypes[stackTraceClass] ??= new InterfaceType(
+            stackTraceClass, const <DartType>[], Nullability.nonNullable);
+  }
+
+  InterfaceType stackTraceRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return stackTraceLegacyRawType;
+      case Nullability.nullable:
+        return stackTraceNullableRawType;
+      case Nullability.nonNullable:
+        return stackTraceNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get streamLegacyRawType {
+    return _streamLegacyRawType ??= _legacyRawTypes[streamClass] ??=
+        new InterfaceType(streamClass, const <DartType>[const DynamicType()],
+            Nullability.legacy);
+  }
+
+  InterfaceType get streamNullableRawType {
+    return _streamNullableRawType ??= _nullableRawTypes[streamClass] ??=
+        new InterfaceType(streamClass, const <DartType>[const DynamicType()],
+            Nullability.nullable);
+  }
+
+  InterfaceType get streamNonNullableRawType {
+    return _streamNonNullableRawType ??= _nonNullableRawTypes[streamClass] ??=
+        new InterfaceType(streamClass, const <DartType>[const DynamicType()],
+            Nullability.nonNullable);
+  }
+
+  InterfaceType streamRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return streamLegacyRawType;
+      case Nullability.nullable:
+        return streamNullableRawType;
+      case Nullability.nonNullable:
+        return streamNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get asyncAwaitCompleterLegacyRawType {
+    return _asyncAwaitCompleterLegacyRawType ??=
+        _legacyRawTypes[asyncAwaitCompleterClass] ??= new InterfaceType(
+            asyncAwaitCompleterClass,
+            const <DartType>[const DynamicType()],
+            Nullability.legacy);
+  }
+
+  InterfaceType get asyncAwaitCompleterNullableRawType {
+    return _asyncAwaitCompleterNullableRawType ??=
+        _nullableRawTypes[asyncAwaitCompleterClass] ??= new InterfaceType(
+            asyncAwaitCompleterClass,
+            const <DartType>[const DynamicType()],
+            Nullability.nullable);
+  }
+
+  InterfaceType get asyncAwaitCompleterNonNullableRawType {
+    return _asyncAwaitCompleterNonNullableRawType ??=
+        _nonNullableRawTypes[asyncAwaitCompleterClass] ??= new InterfaceType(
+            asyncAwaitCompleterClass,
+            const <DartType>[const DynamicType()],
+            Nullability.nonNullable);
+  }
+
+  InterfaceType asyncAwaitCompleterRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return asyncAwaitCompleterLegacyRawType;
+      case Nullability.nullable:
+        return asyncAwaitCompleterNullableRawType;
+      case Nullability.nonNullable:
+        return asyncAwaitCompleterNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get futureOrLegacyRawType {
+    return _futureOrLegacyRawType ??= _legacyRawTypes[futureOrClass] ??=
+        new InterfaceType(futureOrClass, const <DartType>[const DynamicType()],
+            Nullability.legacy);
+  }
+
+  InterfaceType get futureOrNullableRawType {
+    return _futureOrNullableRawType ??= _nullableRawTypes[futureOrClass] ??=
+        new InterfaceType(futureOrClass, const <DartType>[const DynamicType()],
+            Nullability.nullable);
+  }
+
+  InterfaceType get futureOrNonNullableRawType {
+    return _futureOrNonNullableRawType ??=
+        _nonNullableRawTypes[futureOrClass] ??= new InterfaceType(futureOrClass,
+            const <DartType>[const DynamicType()], Nullability.nonNullable);
+  }
+
+  InterfaceType futureOrRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return futureOrLegacyRawType;
+      case Nullability.nullable:
+        return futureOrNullableRawType;
+      case Nullability.nonNullable:
+        return futureOrNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType get pragmaLegacyRawType {
+    return _pragmaLegacyRawType ??= _legacyRawTypes[pragmaClass] ??=
+        new InterfaceType(pragmaClass, const <DartType>[], Nullability.legacy);
+  }
+
+  InterfaceType get pragmaNullableRawType {
+    return _pragmaNullableRawType ??= _nullableRawTypes[pragmaClass] ??=
+        new InterfaceType(
+            pragmaClass, const <DartType>[], Nullability.nullable);
+  }
+
+  InterfaceType get pragmaNonNullableRawType {
+    return _pragmaNonNullableRawType ??= _nonNullableRawTypes[pragmaClass] ??=
+        new InterfaceType(
+            pragmaClass, const <DartType>[], Nullability.nonNullable);
+  }
+
+  InterfaceType pragmaRawType(Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return pragmaLegacyRawType;
+      case Nullability.nullable:
+        return pragmaNullableRawType;
+      case Nullability.nonNullable:
+        return pragmaNonNullableRawType;
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
+
+  InterfaceType legacyRawType(Class klass) {
+    // TODO(dmitryas): Consider using computeBounds instead of DynamicType here.
+    return _legacyRawTypes[klass] ??= new InterfaceType(
+        klass,
+        new List<DartType>.filled(
+            klass.typeParameters.length, const DynamicType()),
+        Nullability.legacy);
+  }
+
+  InterfaceType nullableRawType(Class klass) {
+    // TODO(dmitryas): Consider using computeBounds instead of DynamicType here.
+    return _nullableRawTypes[klass] ??= new InterfaceType(
+        klass,
+        new List<DartType>.filled(
+            klass.typeParameters.length, const DynamicType()),
+        Nullability.nullable);
+  }
+
+  InterfaceType nonNullableRawType(Class klass) {
+    // TODO(dmitryas): Consider using computeBounds instead of DynamicType here.
+    return _nonNullableRawTypes[klass] ??= new InterfaceType(
+        klass,
+        new List<DartType>.filled(
+            klass.typeParameters.length, const DynamicType()),
+        Nullability.nonNullable);
+  }
+
+  InterfaceType rawType(Class klass, Nullability nullability) {
+    switch (nullability) {
+      case Nullability.legacy:
+        return legacyRawType(klass);
+      case Nullability.nullable:
+        return nullableRawType(klass);
+      case Nullability.nonNullable:
+        return nonNullableRawType(klass);
+      case Nullability.neither:
+      default:
+        throw new StateError(
+            "Unsupported nullability $nullability on an InterfaceType.");
+    }
+  }
 }
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index 64e3b5b..57673c6 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -10,10 +10,9 @@
 final List<String> targetNames = targets.keys.toList();
 
 class TargetFlags {
-  final bool legacyMode;
   final bool trackWidgetCreation;
 
-  TargetFlags({this.legacyMode = false, this.trackWidgetCreation = false});
+  TargetFlags({this.trackWidgetCreation = false});
 }
 
 typedef Target _TargetBuilder(TargetFlags flags);
@@ -112,8 +111,6 @@
   /// transformations.
   Map<String, List<String>> get requiredSdkClasses => CoreTypes.requiredClasses;
 
-  bool get legacyMode;
-
   /// A derived class may change this to `true` to enable forwarders to
   /// user-defined `noSuchMethod` that are generated for each abstract member
   /// if such `noSuchMethod` is present.
@@ -274,7 +271,6 @@
 
   NoneTarget(this.flags);
 
-  bool get legacyMode => flags.legacyMode;
   String get name => 'none';
   List<String> get extraRequiredLibraries => <String>[];
   void performModularTransformationsOnLibraries(
diff --git a/pkg/kernel/lib/testing/mock_sdk_component.dart b/pkg/kernel/lib/testing/mock_sdk_component.dart
index c85bdcf..17be30b 100644
--- a/pkg/kernel/lib/testing/mock_sdk_component.dart
+++ b/pkg/kernel/lib/testing/mock_sdk_component.dart
@@ -17,7 +17,7 @@
   }
 
   var objectClass = addClass(coreLib, new Class(name: 'Object'));
-  var objectType = objectClass.rawType;
+  var objectType = new InterfaceType(objectClass);
 
   TypeParameter typeParam(String name, [DartType bound]) {
     return new TypeParameter(name, bound ?? objectType);
diff --git a/pkg/kernel/lib/transformations/continuation.dart b/pkg/kernel/lib/transformations/continuation.dart
index 3e87ef2..d6bf44f 100644
--- a/pkg/kernel/lib/transformations/continuation.dart
+++ b/pkg/kernel/lib/transformations/continuation.dart
@@ -208,7 +208,7 @@
         dartAsyncMarker: AsyncMarker.Sync)
       ..fileOffset = enclosingFunction.fileOffset
       ..fileEndOffset = enclosingFunction.fileEndOffset
-      ..returnType = helper.coreTypes.boolClass.rawType;
+      ..returnType = helper.coreTypes.boolLegacyRawType;
 
     final closureFunction =
         new FunctionDeclaration(nestedClosureVariable, function)
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart
index d368c2d..cfd4617 100644
--- a/pkg/kernel/lib/type_algebra.dart
+++ b/pkg/kernel/lib/type_algebra.dart
@@ -4,6 +4,7 @@
 library kernel.type_algebra;
 
 import 'ast.dart';
+import 'clone.dart';
 
 /// Returns a type where all occurrences of the given type parameters have been
 /// replaced with the corresponding types.
@@ -109,11 +110,25 @@
   for (int i = 0; i < typeParameters.length; ++i) {
     map[typeParameters[i]] = new TypeParameterType(freshParameters[i]);
   }
+  CloneVisitor cloner;
   for (int i = 0; i < typeParameters.length; ++i) {
-    freshParameters[i].bound = substitute(typeParameters[i].bound, map);
-    freshParameters[i].defaultType = typeParameters[i].defaultType != null
-        ? substitute(typeParameters[i].defaultType, map)
+    TypeParameter typeParameter = typeParameters[i];
+    TypeParameter freshTypeParameter = freshParameters[i];
+
+    freshTypeParameter.bound = substitute(typeParameter.bound, map);
+    freshTypeParameter.defaultType = typeParameter.defaultType != null
+        ? substitute(typeParameter.defaultType, map)
         : null;
+    if (typeParameter.annotations.isNotEmpty) {
+      // Annotations can't refer to type parameters, so the cloner shouldn't
+      // perform the substitution.
+      // TODO(dmitryas): Consider rewriting getFreshTypeParameters using cloner
+      // for copying typeParameters as well.
+      cloner ??= new CloneVisitor();
+      for (Expression annotation in typeParameter.annotations) {
+        freshTypeParameter.addAnnotation(cloner.clone(annotation));
+      }
+    }
   }
   return new FreshTypeParameters(freshParameters, Substitution.fromMap(map));
 }
diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart
index 6c9af84..90fff29 100644
--- a/pkg/kernel/lib/type_checker.dart
+++ b/pkg/kernel/lib/type_checker.dart
@@ -344,7 +344,7 @@
         }
         final enclosingFunction = parent as FunctionNode;
         if (enclosingFunction.dartAsyncMarker == AsyncMarker.SyncStar) {
-          return coreTypes.boolClass.rawType;
+          return coreTypes.boolLegacyRawType;
         }
         return null;
 
@@ -424,7 +424,7 @@
     Constructor target = node.target;
     Arguments arguments = node.arguments;
     Class class_ = target.enclosingClass;
-    handleCall(arguments, target.function.functionType,
+    handleCall(arguments, target.function.thisFunctionType,
         typeParameters: class_.typeParameters);
     return new InterfaceType(target.enclosingClass, arguments.types);
   }
@@ -458,7 +458,7 @@
   @override
   DartType visitFunctionExpression(FunctionExpression node) {
     handleNestedFunctionNode(node.function);
-    return node.function.functionType;
+    return node.function.thisFunctionType;
   }
 
   @override
diff --git a/pkg/kernel/lib/type_environment.dart b/pkg/kernel/lib/type_environment.dart
index 795f9d4..98ef5f2 100644
--- a/pkg/kernel/lib/type_environment.dart
+++ b/pkg/kernel/lib/type_environment.dart
@@ -32,16 +32,18 @@
     return new HierarchyBasedTypeEnvironment(coreTypes, hierarchy);
   }
 
-  InterfaceType get objectType => coreTypes.objectClass.rawType;
-  InterfaceType get nullType => coreTypes.nullClass.rawType;
-  InterfaceType get boolType => coreTypes.boolClass.rawType;
-  InterfaceType get intType => coreTypes.intClass.rawType;
-  InterfaceType get numType => coreTypes.numClass.rawType;
-  InterfaceType get doubleType => coreTypes.doubleClass.rawType;
-  InterfaceType get stringType => coreTypes.stringClass.rawType;
-  InterfaceType get symbolType => coreTypes.symbolClass.rawType;
-  InterfaceType get typeType => coreTypes.typeClass.rawType;
-  InterfaceType get rawFunctionType => coreTypes.functionClass.rawType;
+  // TODO(dmitryas): Remove these getters, use the appropriate member of
+  //  CoreTypes at the call sites instead.
+  InterfaceType get objectType => coreTypes.objectLegacyRawType;
+  InterfaceType get nullType => coreTypes.nullType;
+  InterfaceType get boolType => coreTypes.boolLegacyRawType;
+  InterfaceType get intType => coreTypes.intLegacyRawType;
+  InterfaceType get numType => coreTypes.numLegacyRawType;
+  InterfaceType get doubleType => coreTypes.doubleLegacyRawType;
+  InterfaceType get stringType => coreTypes.stringLegacyRawType;
+  InterfaceType get symbolType => coreTypes.symbolLegacyRawType;
+  InterfaceType get typeType => coreTypes.typeLegacyRawType;
+  InterfaceType get rawFunctionType => coreTypes.functionLegacyRawType;
 
   Class get intClass => coreTypes.intClass;
   Class get numClass => coreTypes.numClass;
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index d3dc88e..4f95e65 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -696,7 +696,7 @@
   R visitTypeLiteral(TypeLiteral node, T arg) => defaultExpression(node, arg);
   R visitThisExpression(ThisExpression node, T arg) =>
       defaultExpression(node, arg);
-  R visitConstantExpression(ConstantExpression node, arg) =>
+  R visitConstantExpression(ConstantExpression node, T arg) =>
       defaultExpression(node, arg);
   R visitRethrow(Rethrow node, T arg) => defaultExpression(node, arg);
   R visitThrow(Throw node, T arg) => defaultExpression(node, arg);
diff --git a/pkg/kernel/pubspec.yaml b/pkg/kernel/pubspec.yaml
index d28cdb0..b0b05b0 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.24
+version: 0.3.25
 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/test/class_hierarchy_test.dart b/pkg/kernel/test/class_hierarchy_test.dart
index 6253f4d..c4bdcd8 100644
--- a/pkg/kernel/test/class_hierarchy_test.dart
+++ b/pkg/kernel/test/class_hierarchy_test.dart
@@ -306,7 +306,7 @@
       {Supertype extends_(List<DartType> typeParameterTypes),
       List<Supertype> implements_(List<DartType> typeParameterTypes)}) {
     var typeParameters = typeParameterNames
-        .map((name) => new TypeParameter(name, objectClass.rawType))
+        .map((name) => new TypeParameter(name, coreTypes.objectLegacyRawType))
         .toList();
     var typeParameterTypes = typeParameters
         .map((parameter) => new TypeParameterType(parameter))
@@ -521,12 +521,12 @@
   }
 
   void test_getClassAsInstanceOf_generic_extends() {
-    var int = coreTypes.intClass.rawType;
-    var bool = coreTypes.boolClass.rawType;
+    var int = coreTypes.intLegacyRawType;
+    var bool = coreTypes.boolLegacyRawType;
 
     var a = addGenericClass('A', ['T', 'U']);
 
-    var bT = new TypeParameter('T', objectClass.rawType);
+    var bT = new TypeParameter('T', coreTypes.objectLegacyRawType);
     var bTT = new TypeParameterType(bT);
     var b = addClass(new Class(
         name: 'B',
@@ -549,12 +549,12 @@
   }
 
   void test_getClassAsInstanceOf_generic_implements() {
-    var int = coreTypes.intClass.rawType;
-    var bool = coreTypes.boolClass.rawType;
+    var int = coreTypes.intLegacyRawType;
+    var bool = coreTypes.boolLegacyRawType;
 
     var a = addGenericClass('A', ['T', 'U']);
 
-    var bT = new TypeParameter('T', objectClass.rawType);
+    var bT = new TypeParameter('T', coreTypes.objectLegacyRawType);
     var bTT = new TypeParameterType(bT);
     var b = addClass(new Class(
         name: 'B',
@@ -583,12 +583,12 @@
   }
 
   void test_getClassAsInstanceOf_generic_with() {
-    var int = coreTypes.intClass.rawType;
-    var bool = coreTypes.boolClass.rawType;
+    var int = coreTypes.intLegacyRawType;
+    var bool = coreTypes.boolLegacyRawType;
 
     var a = addGenericClass('A', ['T', 'U']);
 
-    var bT = new TypeParameter('T', objectClass.rawType);
+    var bT = new TypeParameter('T', coreTypes.objectLegacyRawType);
     var bTT = new TypeParameterType(bT);
     var b = addClass(new Class(
         name: 'B',
@@ -1195,12 +1195,12 @@
   }
 
   void test_getTypeAsInstanceOf_generic_extends() {
-    var int = coreTypes.intClass.rawType;
-    var bool = coreTypes.boolClass.rawType;
+    var int = coreTypes.intLegacyRawType;
+    var bool = coreTypes.boolLegacyRawType;
 
     var a = addGenericClass('A', ['T', 'U']);
 
-    var bT = new TypeParameter('T', objectClass.rawType);
+    var bT = new TypeParameter('T', coreTypes.objectLegacyRawType);
     var bTT = new TypeParameterType(bT);
     var b = addClass(new Class(
         name: 'B',
diff --git a/pkg/kernel/test/type_parser.dart b/pkg/kernel/test/type_parser.dart
index a534824..e4b88ae 100644
--- a/pkg/kernel/test/type_parser.dart
+++ b/pkg/kernel/test/type_parser.dart
@@ -328,7 +328,9 @@
   TreeNode lookup(String name) {
     return name.length == 1
         ? typeParameters.putIfAbsent(
-            name, () => new TypeParameter(name, lookupClass('Object').rawType))
+            name,
+            () => new TypeParameter(
+                name, new InterfaceType(lookupClass('Object'))))
         : lookupClass(name);
   }
 
diff --git a/pkg/kernel/test/typedef_unalias_test.dart b/pkg/kernel/test/typedef_unalias_test.dart
index 9457680..f9d448b 100644
--- a/pkg/kernel/test/typedef_unalias_test.dart
+++ b/pkg/kernel/test/typedef_unalias_test.dart
@@ -15,10 +15,10 @@
 
 main() {
   harnessTest('`Foo` where typedef Foo = C', (TestHarness harness) {
-    var foo = new Typedef('Foo', harness.otherClass.rawType);
+    var foo = new Typedef('Foo', harness.otherLegacyRawType);
     harness.enclosingLibrary.addTypedef(foo);
     var type = new TypedefType(foo);
-    expect(type.unalias, equals(harness.otherClass.rawType));
+    expect(type.unalias, equals(harness.otherLegacyRawType));
   });
   harnessTest('`Foo<Obj>` where typedef Foo<T> = C<T>', (TestHarness harness) {
     var param = harness.makeTypeParameter('T');
@@ -26,9 +26,9 @@
         new InterfaceType(harness.otherClass, [new TypeParameterType(param)]),
         typeParameters: [param]);
     harness.enclosingLibrary.addTypedef(foo);
-    var input = new TypedefType(foo, [harness.objectClass.rawType]);
+    var input = new TypedefType(foo, [harness.objectLegacyRawType]);
     var expected =
-        new InterfaceType(harness.otherClass, [harness.objectClass.rawType]);
+        new InterfaceType(harness.otherClass, [harness.objectLegacyRawType]);
     expect(input.unalias, equals(expected));
   });
   harnessTest('`Bar<Obj>` where typedef Bar<T> = Foo<T>, Foo<T> = C<T>',
@@ -45,9 +45,9 @@
         typeParameters: [barParam]);
     harness.enclosingLibrary.addTypedef(foo);
     harness.enclosingLibrary.addTypedef(bar);
-    var input = new TypedefType(bar, [harness.objectClass.rawType]);
+    var input = new TypedefType(bar, [harness.objectLegacyRawType]);
     var expected =
-        new InterfaceType(harness.otherClass, [harness.objectClass.rawType]);
+        new InterfaceType(harness.otherClass, [harness.objectLegacyRawType]);
     expect(input.unalias, equals(expected));
   });
   harnessTest('`Foo<Foo<C>>` where typedef Foo<T> = C<T>',
@@ -58,10 +58,10 @@
         typeParameters: [param]);
     harness.enclosingLibrary.addTypedef(foo);
     var input = new TypedefType(foo, [
-      new TypedefType(foo, [harness.objectClass.rawType])
+      new TypedefType(foo, [harness.objectLegacyRawType])
     ]);
     var expected = new InterfaceType(harness.otherClass, [
-      new TypedefType(foo, [harness.objectClass.rawType])
+      new TypedefType(foo, [harness.objectLegacyRawType])
     ]);
     expect(input.unalias, equals(expected));
   });
diff --git a/pkg/kernel/test/verify_test.dart b/pkg/kernel/test/verify_test.dart
index 7f32330..56498c6 100644
--- a/pkg/kernel/test/verify_test.dart
+++ b/pkg/kernel/test/verify_test.dart
@@ -274,7 +274,7 @@
   });
   positiveTest('Valid typedef Foo = `(C) => void`', (TestHarness test) {
     var typedef_ = new Typedef(
-        'Foo', new FunctionType([test.otherClass.rawType], const VoidType()));
+        'Foo', new FunctionType([test.otherLegacyRawType], const VoidType()));
     test.addNode(typedef_);
   });
   positiveTest('Valid typedef Foo = C<dynamic>', (TestHarness test) {
@@ -286,7 +286,7 @@
     var foo = new Typedef('Foo', null);
     var bar = new Typedef('Bar', null);
     foo.type = new TypedefType(bar);
-    bar.type = test.otherClass.rawType;
+    bar.type = test.otherLegacyRawType;
     test.enclosingLibrary.addTypedef(foo);
     test.enclosingLibrary.addTypedef(bar);
   });
@@ -294,13 +294,13 @@
     var foo = new Typedef('Foo', null);
     var bar = new Typedef('Bar', null);
     foo.type = new InterfaceType(test.otherClass, [new TypedefType(bar)]);
-    bar.type = test.otherClass.rawType;
+    bar.type = test.otherLegacyRawType;
     test.enclosingLibrary.addTypedef(foo);
     test.enclosingLibrary.addTypedef(bar);
   });
   positiveTest('Valid typedef type in field', (TestHarness test) {
     var typedef_ = new Typedef(
-        'Foo', new FunctionType([test.otherClass.rawType], const VoidType()));
+        'Foo', new FunctionType([test.otherLegacyRawType], const VoidType()));
     var field = new Field(new Name('field'),
         type: new TypedefType(typedef_), isStatic: true);
     test.enclosingLibrary.addTypedef(typedef_);
@@ -396,14 +396,14 @@
     first.type = new TypedefType(typedef_);
   });
   positiveTest('Valid typedef Foo<T extends C> = C<T>', (TestHarness test) {
-    var param = new TypeParameter('T', test.otherClass.rawType);
+    var param = new TypeParameter('T', test.otherLegacyRawType);
     var foo = new Typedef('Foo',
         new InterfaceType(test.otherClass, [new TypeParameterType(param)]),
         typeParameters: [param]);
     test.addNode(foo);
   });
   positiveTest('Valid typedef Foo<T extends C<T>> = C<T>', (TestHarness test) {
-    var param = new TypeParameter('T', test.otherClass.rawType);
+    var param = new TypeParameter('T', test.otherLegacyRawType);
     param.bound =
         new InterfaceType(test.otherClass, [new TypeParameterType(param)]);
     var foo = new Typedef('Foo',
@@ -458,7 +458,7 @@
           " but the typedef declares 1 parameters.", (TestHarness test) {
     var param = test.makeTypeParameter('T');
     var foo =
-        new Typedef('Foo', test.otherClass.rawType, typeParameters: [param]);
+        new Typedef('Foo', test.otherLegacyRawType, typeParameters: [param]);
     var field = new Field(new Name('field'),
         type: new TypedefType(foo, []), isStatic: true);
     test.enclosingLibrary.addTypedef(foo);
@@ -468,7 +468,7 @@
       'Dangling typedef reference',
       "Dangling reference to 'typedef Foo = test_lib::OtherClass<dynamic>*;\n'"
           ", parent is: 'null'", (TestHarness test) {
-    var foo = new Typedef('Foo', test.otherClass.rawType, typeParameters: []);
+    var foo = new Typedef('Foo', test.otherLegacyRawType, typeParameters: []);
     var field = new Field(new Name('field'),
         type: new TypedefType(foo, []), isStatic: true);
     test.enclosingLibrary.addMember(field);
@@ -503,6 +503,10 @@
 
   Class otherClass;
 
+  InterfaceType objectLegacyRawType;
+  InterfaceType enclosingLegacyRawType;
+  InterfaceType otherLegacyRawType;
+
   void addNode(TreeNode node) {
     if (node is Expression) {
       addExpression(node);
@@ -545,7 +549,7 @@
   VariableDeclaration makeVariable() => new VariableDeclaration(null);
 
   TypeParameter makeTypeParameter([String name]) {
-    return new TypeParameter(name, new InterfaceType(objectClass));
+    return new TypeParameter(name, objectLegacyRawType);
   }
 
   TestHarness() {
@@ -558,6 +562,8 @@
     component.libraries.add(stubLibrary..parent = component);
     stubLibrary.name = 'dart.core';
     objectClass = new Class(name: 'Object');
+    objectLegacyRawType =
+        new InterfaceType(objectClass, const <DartType>[], Nullability.legacy);
     stubLibrary.addClass(objectClass);
     enclosingLibrary = new Library(Uri.parse('file://test.dart'));
     component.libraries.add(enclosingLibrary..parent = component);
@@ -567,6 +573,8 @@
         name: 'TestClass',
         typeParameters: [classTypeParameter],
         supertype: objectClass.asRawSupertype);
+    enclosingLegacyRawType = new InterfaceType(enclosingClass,
+        const <DartType>[const DynamicType()], Nullability.legacy);
     enclosingLibrary.addClass(enclosingClass);
     enclosingMember = new Procedure(new Name('test'), ProcedureKind.Method,
         new FunctionNode(new EmptyStatement()));
@@ -575,6 +583,8 @@
         name: 'OtherClass',
         typeParameters: [makeTypeParameter('OtherT')],
         supertype: objectClass.asRawSupertype);
+    otherLegacyRawType = new InterfaceType(
+        otherClass, const <DartType>[const DynamicType()], Nullability.legacy);
     enclosingLibrary.addClass(otherClass);
   }
 }
diff --git a/pkg/nnbd_migration/lib/instrumentation.dart b/pkg/nnbd_migration/lib/instrumentation.dart
new file mode 100644
index 0000000..a108610
--- /dev/null
+++ b/pkg/nnbd_migration/lib/instrumentation.dart
@@ -0,0 +1,259 @@
+// 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/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:nnbd_migration/nnbd_migration.dart';
+import 'package:nnbd_migration/nullability_state.dart';
+
+/// Information exposed to the migration client about the set of nullability
+/// nodes decorating a type in the program being migrated.
+abstract class DecoratedTypeInfo {
+  /// Information about the graph node associated with the decision of whether
+  /// or not to make this type into a nullable type.
+  NullabilityNodeInfo get node;
+
+  /// If [type] is a function type, information about the set of nullability
+  /// nodes decorating the type's return type.
+  DecoratedTypeInfo get returnType;
+
+  /// The original (pre-migration) type that is being migrated.
+  DartType get type;
+
+  /// If [type] is a function type, looks up information about the set of
+  /// nullability nodes decorating one of the type's named parameter types.
+  DecoratedTypeInfo namedParameter(String name);
+
+  /// If [type] is a function type, looks up information about the set of
+  /// nullability nodes decorating one of the type's positional parameter types.
+  /// (This could be an optional or a required positional parameter).
+  DecoratedTypeInfo positionalParameter(int i);
+
+  /// If [type] is an interface type, looks up information about the set of
+  /// nullability nodes decorating one of the type's type arguments.
+  DecoratedTypeInfo typeArgument(int i);
+}
+
+/// Information exposed to the migration client about an edge in the nullability
+/// graph.
+///
+/// A graph edge represents a dependency relationship between two types being
+/// migrated, suggesting that if one type (the source) is made nullable, it may
+/// be desirable to make the other type (the destination) nullable as well.
+abstract class EdgeInfo implements FixReasonInfo {
+  /// Information about the graph node that this edge "points to".
+  NullabilityNodeInfo get destinationNode;
+
+  /// The set of "guard nodes" for this edge.  Guard nodes are graph nodes whose
+  /// nullability determines whether it is important to satisfy a graph edge.
+  /// If at least one of an edge's guards is non-nullable, then it is not
+  /// important to satisfy the graph edge.  (Typically this is because the code
+  /// that led to the graph edge being created is only reachable if the guards
+  /// are all nullable).
+  Iterable<NullabilityNodeInfo> get guards;
+
+  /// A boolean indicating whether the graph edge is a "hard" edge.  Hard edges
+  /// are associated with unconditional control flow, and thus allow information
+  /// about non-nullability to be propagated "upstream" through the nullability
+  /// graph.
+  bool get isHard;
+
+  /// A boolean indicating whether the graph edge is "satisfied".  At its heart,
+  /// the nullability propagation algorithm is an effort to satisfy graph edges
+  /// in a way that corresponds to the user's intent.  A graph edge is
+  /// considered satisfied if any of the following is true:
+  /// - Its [sourceNode] is non-nullable.
+  /// - One of its [guards] is non-nullable.
+  /// - Its [destinationNode] is nullable.
+  bool get isSatisfied;
+
+  /// A boolean indicating whether the graph edge is a "union" edge.  Union
+  /// edges are edges for which the nullability propagation algorithm tries to
+  /// ensure that both the [sourceNode] and the [destinationNode] have the
+  /// same nullability.  Typically these are associated with situations where
+  /// Dart language semantics require two types to be the same type (e.g. a type
+  /// formal bound on a generic function type in a base class, and the
+  /// corresponding type formal bound on a generic function type in an
+  /// overriding class).
+  ///
+  /// The [isHard] property is always true for union edges.
+  bool get isUnion;
+
+  /// Information about the graph node that this edge "points away from".
+  NullabilityNodeInfo get sourceNode;
+}
+
+/// Information exposed to the migration client about the location in source
+/// code that led an edge to be introduced into the nullability graph.
+abstract class EdgeOriginInfo {
+  /// The AST node that led the edge to be introduced into the nullability
+  /// graph.
+  AstNode get node;
+
+  /// The source file that [node] appears in.
+  Source get source;
+}
+
+/// Interface used by the migration engine to expose information to its client
+/// about a reason for a modification to the source file.
+abstract class FixReasonInfo {}
+
+/// Interface used by the migration engine to expose information to its client
+/// about the decisions made during migration, and how those decisions relate to
+/// the input source code.
+abstract class NullabilityMigrationInstrumentation {
+  /// Called whenever an explicit [typeAnnotation] is found in the source code,
+  /// to report the nullability [node] that was associated with this type.  If
+  /// the migration engine determines that the [node] should be nullable, a `?`
+  /// will be inserted after the type annotation.
+  void explicitTypeNullability(
+      Source source, TypeAnnotation typeAnnotation, NullabilityNodeInfo node);
+
+  /// Called whenever reference is made to an [element] outside of the code
+  /// being migrated, to report the nullability nodes associated with the type
+  /// of the element.
+  void externalDecoratedType(Element element, DecoratedTypeInfo decoratedType);
+
+  /// Called whenever a fix is decided upon, to report the reasons for the fix.
+  void fix(SingleNullabilityFix fix, Iterable<FixReasonInfo> reasons);
+
+  /// Called whenever the migration engine creates a graph edge between
+  /// nullability nodes, to report information about the edge that was created,
+  /// and why it was created.
+  void graphEdge(EdgeInfo edge, EdgeOriginInfo originInfo);
+
+  /// Called when the migration engine start up, to report information about the
+  /// immutable migration nodes [never] and [always] that are used as the
+  /// starting point for nullability propagation.
+  void immutableNodes(NullabilityNodeInfo never, NullabilityNodeInfo always);
+
+  /// Called whenever the migration engine encounters an implicit return type
+  /// associated with an AST node, to report the nullability nodes associated
+  /// with the implicit return type of the AST node.
+  ///
+  /// [node] is the AST node having an implicit return type; it may be an
+  /// executable declaration, function-typed formal parameter declaration,
+  /// function type alias declaration, GenericFunctionType, or a function
+  /// expression.
+  void implicitReturnType(
+      Source source, AstNode node, DecoratedTypeInfo decoratedReturnType);
+
+  /// Called whenever the migration engine encounters an implicit type
+  /// associated with an AST node, to report the nullability nodes associated
+  /// with the implicit type of the AST node.
+  ///
+  /// [node] is the AST node having an implicit type; it may be a formal
+  /// parameter, a declared identifier, or a variable in a variable declaration
+  /// list.
+  void implicitType(
+      Source source, AstNode node, DecoratedTypeInfo decoratedType);
+
+  /// Called whenever the migration engine encounters an AST node with implicit
+  /// type arguments, to report the nullability nodes associated with the
+  /// implicit type arguments of the AST node.
+  ///
+  /// [node] is the AST node having implicit type arguments; it may be a
+  /// constructor redirection, function expression invocation, method
+  /// invocation, instance creation expression, list/map/set literal, or type
+  /// annotation.
+  void implicitTypeArguments(
+      Source source, AstNode node, Iterable<DecoratedTypeInfo> types);
+
+  /// Called whenever the migration engine performs a step in the propagation of
+  /// nullability information through the nullability graph, to report details
+  /// of the step that was performed and why.
+  void propagationStep(PropagationInfo info);
+}
+
+/// Information exposed to the migration client about a single node in the
+/// nullability graph.
+abstract class NullabilityNodeInfo implements FixReasonInfo {
+  /// Indicates whether the node is immutable.  The only immutable nodes in the
+  /// nullability graph are the nodes `never` and `always` that are used as the
+  /// starting points for nullability propagation.
+  bool get isImmutable;
+
+  /// After migration is complete, this getter can be used to query whether
+  /// the type associated with this node was determined to be nullable.
+  bool get isNullable;
+}
+
+/// Information exposed to the migration client about a single step in the
+/// nullability propagation algorithm, in which the nullability state of a
+/// single node was changed.
+abstract class PropagationInfo {
+  /// The edge that caused the nullability state of [node] to be set to
+  /// [newState], or `null` if the nullability state was changed for reasons
+  /// not associated with an edge.  Will be `null` when [reason] is
+  /// [StateChangeReason.substituteInner] or
+  /// [StateChangeReason.substituteOuter], non-null otherwise.
+  EdgeInfo get edge;
+
+  /// The new state that [node] was placed into.
+  NullabilityState get newState;
+
+  /// The nullability node whose state was changed.
+  NullabilityNodeInfo get node;
+
+  /// The reason the nullability node's state was changed.
+  StateChangeReason get reason;
+
+  /// The substitution node that caused the nullability state of [node] to be
+  /// set to [newState], or `null` if the nullability state was changed for
+  /// reasons not associated with a substitution node.  Will be non-null when
+  /// [reason] is [StateChangeReason.substituteInner] or
+  /// [StateChangeReason.substituteOuter], `null` otherwise.
+  SubstitutionNodeInfo get substitutionNode;
+}
+
+/// Enum representing the various reasons why a nullability node might change
+/// state during nullability propagation.
+enum StateChangeReason {
+  /// A union edge exists between this node and a node that is known a priori to
+  /// be nullable, so this node is being made nullable as well.
+  union,
+
+  /// A hard or union edge exists whose source is this node, and whose
+  /// destination is non-nullable, so this node is being made non-nullable as
+  /// well.
+  upstream,
+
+  /// An edge exists whose destination is this node, and whose source is
+  /// nullable, so this node is being made nullable as well.
+  downstream,
+
+  /// An edge exists whose source is this node, and whose destination is exact
+  /// nullable, so this node is being made exact nullable as well.
+  exactUpstream,
+
+  /// A substitution node exists whose inner node points to this node, and the
+  /// substitution node is nullable, so this node is being made nullable as
+  /// well.
+  substituteInner,
+
+  /// A substitution node exists whose outer node points to this node, and the
+  /// substitution node is nullable, so this node is being made nullable as
+  /// well.
+  substituteOuter,
+}
+
+/// Information exposed to the migration client about a node in the nullability
+/// graph resulting from a type substitution.
+abstract class SubstitutionNodeInfo extends NullabilityNodeInfo {
+  /// Nullability node representing the inner type of the substitution.
+  ///
+  /// For example, if this NullabilityNode arose from substituting `int*` for
+  /// `T` in the type `T*`, [innerNode] is the nullability corresponding to the
+  /// `*` in `int*`.
+  NullabilityNodeInfo get innerNode;
+
+  /// Nullability node representing the outer type of the substitution.
+  ///
+  /// For example, if this NullabilityNode arose from substituting `int*` for
+  /// `T` in the type `T*`, [innerNode] is the nullability corresponding to the
+  /// `*` in `T*`.
+  NullabilityNodeInfo get outerNode;
+}
diff --git a/pkg/nnbd_migration/lib/nnbd_migration.dart b/pkg/nnbd_migration/lib/nnbd_migration.dart
index e20f78f..8bb4062 100644
--- a/pkg/nnbd_migration/lib/nnbd_migration.dart
+++ b/pkg/nnbd_migration/lib/nnbd_migration.dart
@@ -7,6 +7,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:meta/meta.dart';
+import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/src/nullability_migration_impl.dart';
 
 /// Description of fixes that might be performed by nullability migration.
@@ -68,7 +69,9 @@
   /// complete.  TODO(paulberry): remove this mode once the migration algorithm
   /// is fully implemented.
   factory NullabilityMigration(NullabilityMigrationListener listener,
-      {bool permissive}) = NullabilityMigrationImpl;
+          {bool permissive,
+          NullabilityMigrationInstrumentation instrumentation}) =
+      NullabilityMigrationImpl;
 
   void finish();
 
diff --git a/pkg/nnbd_migration/lib/nullability_state.dart b/pkg/nnbd_migration/lib/nullability_state.dart
new file mode 100644
index 0000000..fdeda46
--- /dev/null
+++ b/pkg/nnbd_migration/lib/nullability_state.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.
+
+/// State of a nullability node.
+class NullabilityState {
+  /// State of a nullability node whose nullability hasn't been decided yet.
+  static const undetermined = NullabilityState._('undetermined', false);
+
+  /// State of a nullability node that has been determined to be non-nullable
+  /// by propagating upstream.
+  static const nonNullable = NullabilityState._('non-nullable', false);
+
+  /// State of a nullability node that has been determined to be nullable by
+  /// propagating downstream.
+  static const ordinaryNullable = NullabilityState._('ordinary nullable', true);
+
+  /// State of a nullability node that has been determined to be nullable by
+  /// propagating upstream from a contravariant use of a generic.
+  static const exactNullable = NullabilityState._('exact nullable', true);
+
+  /// Name of the state (for use in debugging).
+  final String name;
+
+  /// Indicates whether the given state should be considered nullable.
+  ///
+  /// After propagation, any nodes that remain in the undetermined state are
+  /// considered to be non-nullable, so this field is returns `false` for nodes
+  /// in that state.
+  final bool isNullable;
+
+  const NullabilityState._(this.name, this.isNullable);
+
+  @override
+  String toString() => name;
+}
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 f34d762..23c98c2 100644
--- a/pkg/nnbd_migration/lib/src/already_migrated_code_decorator.dart
+++ b/pkg/nnbd_migration/lib/src/already_migrated_code_decorator.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/type.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -89,11 +90,10 @@
     allSupertypes.addAll(class_.superclassConstraints);
     allSupertypes.addAll(class_.interfaces);
     allSupertypes.addAll(class_.mixins);
-    var type = class_.type;
+    var type = class_.thisType;
     if (type.isDartAsyncFuture) {
       // Add FutureOr<T> as a supertype of Future<T>.
-      allSupertypes
-          .add(_typeProvider.futureOrType.instantiate(type.typeArguments));
+      allSupertypes.add(_typeProvider.futureOrType2(type.typeArguments.single));
     }
     return allSupertypes.map(decorate);
   }
diff --git a/pkg/nnbd_migration/lib/src/conditional_discard.dart b/pkg/nnbd_migration/lib/src/conditional_discard.dart
index 144bd82..0295834 100644
--- a/pkg/nnbd_migration/lib/src/conditional_discard.dart
+++ b/pkg/nnbd_migration/lib/src/conditional_discard.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:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
 
 /// Container for information gathered during nullability migration about a
@@ -48,4 +49,10 @@
   /// Indicates whether the code path that results from the condition evaluating
   /// to `true` is reachable after migration.
   bool get keepTrue => trueGuard == null || trueGuard.isNullable;
+
+  @override
+  Iterable<FixReasonInfo> get reasons sync* {
+    if (!keepTrue) yield falseGuard;
+    if (!keepFalse) yield trueGuard;
+  }
 }
diff --git a/pkg/nnbd_migration/lib/src/decorated_class_hierarchy.dart b/pkg/nnbd_migration/lib/src/decorated_class_hierarchy.dart
index 8c46c9e..3935f4d4 100644
--- a/pkg/nnbd_migration/lib/src/decorated_class_hierarchy.dart
+++ b/pkg/nnbd_migration/lib/src/decorated_class_hierarchy.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:nnbd_migration/src/decorated_type.dart';
 import 'package:nnbd_migration/src/node_builder.dart';
@@ -53,7 +54,13 @@
       ClassElement class_, ClassElement superclass) {
     assert(!(class_.library.isDartCore && class_.name == 'Null'));
     if (superclass.typeParameters.isEmpty) {
-      return DecoratedType(superclass.type, _graph.never);
+      return DecoratedType(
+        superclass.instantiate(
+          typeArguments: const [],
+          nullabilitySuffix: NullabilitySuffix.none,
+        ),
+        _graph.never,
+      );
     }
     return _getGenericSupertypeDecorations(class_)[superclass] ??
         (throw StateError('Unrelated types: $class_ and $superclass'));
diff --git a/pkg/nnbd_migration/lib/src/decorated_type.dart b/pkg/nnbd_migration/lib/src/decorated_type.dart
index 9982d1f..8cb67ac 100644
--- a/pkg/nnbd_migration/lib/src/decorated_type.dart
+++ b/pkg/nnbd_migration/lib/src/decorated_type.dart
@@ -6,13 +6,15 @@
 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/resolver.dart';
+import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
 
 /// Representation of a type in the code to be migrated.  In addition to
 /// tracking the (unmigrated) [DartType], we track the [ConstraintVariable]s
 /// indicating whether the type, and the types that compose it, are nullable.
-class DecoratedType {
+class DecoratedType implements DecoratedTypeInfo {
   /// Mapping from type parameter elements to the decorated types of those type
   /// parameters' bounds.
   ///
@@ -21,11 +23,13 @@
   /// stored in [Variables._decoratedTypeParameterBounds].
   static final _decoratedTypeParameterBounds = Expando<DecoratedType>();
 
+  @override
   final DartType type;
 
+  @override
   final NullabilityNode node;
 
-  /// If `this` is a function type, the [DecoratedType] of its return type.
+  @override
   final DecoratedType returnType;
 
   /// If `this` is a function type, the [DecoratedType] of each of its
@@ -319,6 +323,12 @@
         type.instantiate(undecoratedArgumentTypes), substitution);
   }
 
+  @override
+  DecoratedTypeInfo namedParameter(String name) => namedParameters[name];
+
+  @override
+  DecoratedTypeInfo positionalParameter(int i) => positionalParameters[i];
+
   /// Apply the given [substitution] to this type.
   ///
   /// [undecoratedResult] is the result of the substitution, as determined by
@@ -328,13 +338,10 @@
       [DartType undecoratedResult]) {
     if (substitution.isEmpty) return this;
     if (undecoratedResult == null) {
-      List<DartType> argumentTypes = [];
-      List<DartType> parameterTypes = [];
-      for (var entry in substitution.entries) {
-        argumentTypes.add(entry.value.type);
-        parameterTypes.add(entry.key.type);
-      }
-      undecoratedResult = type.substitute2(argumentTypes, parameterTypes);
+      undecoratedResult = Substitution.fromPairs(
+        substitution.keys.toList(),
+        substitution.values.map((d) => d.type).toList(),
+      ).substituteType(type);
     }
     return _substitute(substitution, undecoratedResult);
   }
@@ -387,6 +394,9 @@
     }
   }
 
+  @override
+  DecoratedTypeInfo typeArgument(int i) => typeArguments[i];
+
   /// Creates a shallow copy of `this`, replacing the nullability node.
   DecoratedType withNode(NullabilityNode node) => DecoratedType(type, node,
       returnType: returnType,
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index f802599..1663b16 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -16,6 +16,7 @@
 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';
 import 'package:nnbd_migration/src/conditional_discard.dart';
 import 'package:nnbd_migration/src/decorated_class_hierarchy.dart';
@@ -96,6 +97,8 @@
 
   final NullabilityMigrationListener /*?*/ listener;
 
+  final NullabilityMigrationInstrumentation /*?*/ instrumentation;
+
   final NullabilityGraph _graph;
 
   TypeProvider _typeProvider;
@@ -189,7 +192,8 @@
   List<String> _objectGetNames;
 
   EdgeBuilder(this._typeProvider, this._typeSystem, this._variables,
-      this._graph, this.source, this.listener)
+      this._graph, this.source, this.listener,
+      {this.instrumentation})
       : _decoratedClassHierarchy = DecoratedClassHierarchy(_variables, _graph),
         _inheritanceManager = InheritanceManager3(_typeSystem),
         _notNullType = DecoratedType(_typeProvider.objectType, _graph.never),
@@ -263,7 +267,22 @@
       var intentNode = _conditionInfo.trueDemonstratesNonNullIntent;
       if (intentNode != null && _conditionInfo.postDominatingIntent) {
         _graph.connect(_conditionInfo.trueDemonstratesNonNullIntent,
-            _graph.never, NonNullAssertionOrigin(source, node.offset),
+            _graph.never, NonNullAssertionOrigin(source, node),
+            hard: true);
+      }
+    }
+    node.message?.accept(this);
+    return null;
+  }
+
+  @override
+  DecoratedType visitAssertInitializer(AssertInitializer node) {
+    _checkExpressionNotNull(node.condition);
+    if (identical(_conditionInfo?.condition, node.condition)) {
+      var intentNode = _conditionInfo.trueDemonstratesNonNullIntent;
+      if (intentNode != null && _conditionInfo.postDominatingIntent) {
+        _graph.connect(_conditionInfo.trueDemonstratesNonNullIntent,
+            _graph.never, NonNullAssertionOrigin(source, node),
             hard: true);
       }
     }
@@ -273,17 +292,16 @@
 
   @override
   DecoratedType visitAssignmentExpression(AssignmentExpression node) {
-    _CompoundOperatorInfo compoundOperatorInfo;
     bool isQuestionAssign = false;
+    bool isCompound = false;
     if (node.operator.type == TokenType.QUESTION_QUESTION_EQ) {
       isQuestionAssign = true;
     } else if (node.operator.type != TokenType.EQ) {
-      compoundOperatorInfo = _CompoundOperatorInfo(
-          node.staticElement, node.operator.offset, node.staticType);
+      isCompound = true;
     }
     var expressionType = _handleAssignment(node.rightHandSide,
         destinationExpression: node.leftHandSide,
-        compoundOperatorInfo: compoundOperatorInfo,
+        compoundOperatorInfo: isCompound ? node : null,
         questionAssignNode: isQuestionAssign ? node : null);
     var conditionalNode = _conditionalNodes[node.leftHandSide];
     if (conditionalNode != null) {
@@ -356,8 +374,8 @@
         });
         var ifNullNode = NullabilityNode.forIfNotNull();
         expressionType = DecoratedType(node.staticType, ifNullNode);
-        _connect(rightType.node, expressionType.node,
-            IfNullOrigin(source, node.offset));
+        _connect(
+            rightType.node, expressionType.node, IfNullOrigin(source, node));
       } finally {
         _flowAnalysis.ifNullExpression_end();
         _guards.removeLast();
@@ -461,7 +479,7 @@
               .asSubstitution);
       var superConstructorDecoratedType =
           _variables.decoratedElementType(superConstructorElement);
-      var origin = ImplicitMixinSuperCallOrigin(source, node.offset);
+      var origin = ImplicitMixinSuperCallOrigin(source, node);
       _unionDecoratedTypeParameters(
           constructorDecoratedType, superConstructorDecoratedType, origin);
     }
@@ -546,7 +564,7 @@
         _connect(
             _graph.always,
             getOrComputeElementType(node.declaredElement).node,
-            OptionalFormalParameterOrigin(source, node.offset));
+            OptionalFormalParameterOrigin(source, node));
       }
     } else {
       _handleAssignment(defaultValue,
@@ -604,7 +622,7 @@
     var parameterElement = node.declaredElement as FieldFormalParameterElement;
     var parameterType = _variables.decoratedElementType(parameterElement);
     var fieldType = _variables.decoratedElementType(parameterElement.field);
-    var origin = FieldFormalParameterOrigin(source, node.offset);
+    var origin = FieldFormalParameterOrigin(source, node);
     if (node.type == null) {
       _unionDecoratedTypes(parameterType, fieldType, origin);
     } else {
@@ -799,6 +817,8 @@
         decoratedTypeArguments = typeArgumentTypes
             .map((t) => DecoratedType.forImplicitType(_typeProvider, t, _graph))
             .toList();
+        instrumentation?.implicitTypeArguments(
+            source, node, decoratedTypeArguments);
       } else {
         // Note: this could happen if the code being migrated has errors.
         typeArgumentTypes = const [];
@@ -821,16 +841,36 @@
   @override
   DecoratedType visitIsExpression(IsExpression node) {
     var type = node.type;
-    if (type is NamedType && type.typeArguments != null) {
-      // TODO(brianwilkerson) Figure out what constraints we need to add to
-      //  allow the tool to decide whether to make the type arguments nullable.
-      // TODO(brianwilkerson)
-      _unimplemented(node, 'Is expression with type arguments');
+    type.accept(this);
+    var decoratedType = _variables.decoratedTypeAnnotation(source, type);
+    if (type is NamedType) {
+      // The main type of the is check historically could not be nullable.
+      // Making it nullable could change runtime behavior.
+      _connect(decoratedType.node, _graph.never,
+          IsCheckMainTypeOrigin(source, type));
+      if (type.typeArguments != null) {
+        // TODO(mfairhurst): connect arguments to the expression type when they
+        // relate.
+        type.typeArguments.arguments.forEach((argument) {
+          _connect(
+              _graph.always,
+              _variables.decoratedTypeAnnotation(source, argument).node,
+              IsCheckComponentTypeOrigin(source, argument));
+        });
+      }
     } else if (type is GenericFunctionType) {
       // TODO(brianwilkerson)
       _unimplemented(node, 'Is expression with GenericFunctionType');
     }
-    node.visitChildren(this);
+    var expression = node.expression;
+    expression.accept(this);
+    if (expression is SimpleIdentifier) {
+      var element = expression.staticElement;
+      if (element is VariableElement) {
+        _flowAnalysis.isExpression_end(
+            node, element, node.notOperator != null, decoratedType);
+      }
+    }
     return DecoratedType(node.staticType, _graph.never);
   }
 
@@ -854,8 +894,10 @@
     try {
       var listType = node.staticType as InterfaceType;
       if (node.typeArguments == null) {
-        _currentLiteralElementType = DecoratedType.forImplicitType(
+        var elementType = DecoratedType.forImplicitType(
             _typeProvider, listType.typeArguments[0], _graph);
+        instrumentation?.implicitTypeArguments(source, node, [elementType]);
+        _currentLiteralElementType = elementType;
       } else {
         _currentLiteralElementType = _variables.decoratedTypeAnnotation(
             source, node.typeArguments.arguments[0]);
@@ -1082,8 +1124,10 @@
       try {
         if (typeArguments == null) {
           assert(setOrMapType.typeArguments.length == 1);
-          _currentLiteralElementType = DecoratedType.forImplicitType(
+          var elementType = DecoratedType.forImplicitType(
               _typeProvider, setOrMapType.typeArguments[0], _graph);
+          instrumentation?.implicitTypeArguments(source, node, [elementType]);
+          _currentLiteralElementType = elementType;
         } else {
           assert(typeArguments.length == 1);
           _currentLiteralElementType =
@@ -1103,10 +1147,14 @@
       try {
         if (typeArguments == null) {
           assert(setOrMapType.typeArguments.length == 2);
-          _currentMapKeyType = DecoratedType.forImplicitType(
+          var keyType = DecoratedType.forImplicitType(
               _typeProvider, setOrMapType.typeArguments[0], _graph);
-          _currentMapValueType = DecoratedType.forImplicitType(
+          _currentMapKeyType = keyType;
+          var valueType = DecoratedType.forImplicitType(
               _typeProvider, setOrMapType.typeArguments[1], _graph);
+          _currentMapValueType = valueType;
+          instrumentation
+              ?.implicitTypeArguments(source, node, [keyType, valueType]);
         } else {
           assert(typeArguments.length == 2);
           _currentMapKeyType =
@@ -1157,8 +1205,8 @@
     if (_typeSystem.isSubtypeOf(
         spreadType, _typeProvider.mapObjectObjectType)) {
       assert(_currentMapKeyType != null && _currentMapValueType != null);
-      final expectedType = _typeSystem.instantiateType(_typeProvider.mapType,
-          [_currentMapKeyType.type, _currentMapValueType.type]);
+      final expectedType = _typeProvider.mapType2(
+          _currentMapKeyType.type, _currentMapValueType.type);
       final expectedDecoratedType = DecoratedType.forImplicitType(
           _typeProvider, expectedType, _graph,
           typeArguments: [_currentMapKeyType, _currentMapValueType]);
@@ -1168,8 +1216,8 @@
     } else if (_typeSystem.isSubtypeOf(
         spreadType, _typeProvider.iterableDynamicType)) {
       assert(_currentLiteralElementType != null);
-      final expectedType = _typeSystem.instantiateType(
-          _typeProvider.iterableType, [_currentLiteralElementType.type]);
+      final expectedType =
+          _typeProvider.iterableType2(_currentLiteralElementType.type);
       final expectedDecoratedType = DecoratedType.forImplicitType(
           _typeProvider, expectedType, _graph,
           typeArguments: [_currentLiteralElementType]);
@@ -1290,7 +1338,7 @@
           throw new StateError('No type annotation for type name '
               '${typeName.toSource()}, offset=${typeName.offset}');
         }
-        var origin = InstantiateToBoundsOrigin(source, typeName.offset);
+        var origin = InstantiateToBoundsOrigin(source, typeName);
         for (int i = 0; i < instantiatedType.typeArguments.length; i++) {
           _unionDecoratedTypes(
               instantiatedType.typeArguments[i],
@@ -1335,7 +1383,7 @@
                 '(${initializer.toSource()}) offset=${initializer.offset}');
           }
           _unionDecoratedTypes(initializerType, destinationType,
-              InitializerInferenceOrigin(source, variable.name.offset));
+              InitializerInferenceOrigin(source, variable));
         } else {
           _handleAssignment(initializer, destinationType: destinationType);
         }
@@ -1413,8 +1461,8 @@
       {bool hard = false}) {
     var edge = _graph.connect(source, destination, origin,
         hard: hard, guards: _guards);
-    if (origin is ExpressionChecks) {
-      origin.edges.add(edge);
+    if (origin is ExpressionChecksOrigin) {
+      origin.checks.edges.add(edge);
     }
   }
 
@@ -1545,7 +1593,7 @@
   DecoratedType _handleAssignment(Expression expression,
       {DecoratedType destinationType,
       Expression destinationExpression,
-      _CompoundOperatorInfo compoundOperatorInfo,
+      AssignmentExpression compoundOperatorInfo,
       Expression questionAssignNode,
       bool canInsertChecks = true}) {
     assert(
@@ -1576,16 +1624,18 @@
         throw StateError('No type computed for ${expression.runtimeType} '
             '(${expression.toSource()}) offset=${expression.offset}');
       }
-      ExpressionChecks expressionChecks;
+      ExpressionChecksOrigin expressionChecksOrigin;
       if (canInsertChecks && !sourceType.type.isDynamic) {
-        expressionChecks = ExpressionChecks(expression.end);
-        _variables.recordExpressionChecks(source, expression, expressionChecks);
+        expressionChecksOrigin = ExpressionChecksOrigin(
+            source, expression, ExpressionChecks(expression.end));
+        _variables.recordExpressionChecks(
+            source, expression, expressionChecksOrigin);
       }
       if (compoundOperatorInfo != null) {
-        var compoundOperatorMethod = compoundOperatorInfo.method;
+        var compoundOperatorMethod = compoundOperatorInfo.staticElement;
         if (compoundOperatorMethod != null) {
           _checkAssignment(
-              CompoundAssignmentOrigin(source, compoundOperatorInfo.offset),
+              CompoundAssignmentOrigin(source, compoundOperatorInfo),
               source: destinationType,
               destination: _notNullType,
               hard: _postDominatedLocals
@@ -1593,14 +1643,14 @@
           DecoratedType compoundOperatorType =
               getOrComputeElementType(compoundOperatorMethod);
           assert(compoundOperatorType.positionalParameters.length > 0);
-          _checkAssignment(expressionChecks,
+          _checkAssignment(expressionChecksOrigin,
               source: sourceType,
               destination: compoundOperatorType.positionalParameters[0],
               hard: _postDominatedLocals.isReferenceInScope(expression));
-          sourceType = _fixNumericTypes(compoundOperatorType.returnType,
-              compoundOperatorInfo.undecoratedType);
+          sourceType = _fixNumericTypes(
+              compoundOperatorType.returnType, compoundOperatorInfo.staticType);
           _checkAssignment(
-              CompoundAssignmentOrigin(source, compoundOperatorInfo.offset),
+              CompoundAssignmentOrigin(source, compoundOperatorInfo),
               source: sourceType,
               destination: destinationType,
               hard: false);
@@ -1608,7 +1658,7 @@
           sourceType = _dynamicType;
         }
       } else {
-        _checkAssignment(expressionChecks,
+        _checkAssignment(expressionChecksOrigin,
             source: sourceType,
             destination: destinationType,
             hard: _postDominatedLocals.isReferenceInScope(expression));
@@ -1690,9 +1740,9 @@
       }
       if (declaredElement is! ConstructorElement) {
         var classElement = declaredElement.enclosingElement as ClassElement;
-        var origin = InheritanceOrigin(source, node.offset);
+        var origin = InheritanceOrigin(source, node);
         for (var overriddenElement in _inheritanceManager.getOverridden(
-                classElement.type,
+                classElement.thisType,
                 Name(classElement.library.source.uri, declaredElement.name)) ??
             const <ExecutableElement>[]) {
           if (overriddenElement is ExecutableMember) {
@@ -1787,11 +1837,33 @@
       _flowAnalysis.for_bodyBegin(
           node is Statement ? node : null, parts.condition);
     } else if (parts is ForEachParts) {
+      Element lhsElement;
       if (parts is ForEachPartsWithDeclaration) {
-        _flowAnalysis.add(parts.loopVariable.declaredElement, assigned: true);
+        var variableElement = parts.loopVariable.declaredElement;
+        lhsElement = variableElement;
+        _flowAnalysis.add(variableElement, assigned: false);
+      } else if (parts is ForEachPartsWithIdentifier) {
+        lhsElement = parts.identifier.staticElement;
+      } else {
+        throw StateError(
+            'Unexpected ForEachParts subtype: ${parts.runtimeType}');
       }
-      _checkExpressionNotNull(parts.iterable);
-      _flowAnalysis.forEach_bodyBegin(_assignedVariables.writtenInNode(node));
+      var iterableType = _checkExpressionNotNull(parts.iterable);
+      if (lhsElement != null) {
+        DecoratedType lhsType = _variables.decoratedElementType(lhsElement);
+        var iterableTypeType = iterableType.type;
+        if (_typeSystem.isSubtypeOf(
+            iterableTypeType, _typeProvider.iterableDynamicType)) {
+          var elementType = _decoratedClassHierarchy
+              .asInstanceOf(
+                  iterableType, _typeProvider.iterableDynamicType.element)
+              .typeArguments[0];
+          _checkAssignment(ForEachVariableOrigin(source, parts),
+              source: elementType, destination: lhsType, hard: false);
+        }
+      }
+      _flowAnalysis.forEach_bodyBegin(_assignedVariables.writtenInNode(node),
+          lhsElement is VariableElement ? lhsElement : null);
     }
 
     // The condition may fail/iterable may be empty, so the body gets a new
@@ -1859,6 +1931,7 @@
               .map((argType) =>
                   DecoratedType.forImplicitType(_typeProvider, argType, _graph))
               .toList();
+          instrumentation?.implicitTypeArguments(source, node, argumentTypes);
           calleeType = calleeType.instantiate(argumentTypes);
         } else if (constructorTypeParameters != null) {
           // No need to instantiate; caller has already substituted in the
@@ -1907,8 +1980,8 @@
     // Any parameters not supplied must be optional.
     for (var entry in calleeType.namedParameters.entries) {
       if (suppliedNamedParameters.contains(entry.key)) continue;
-      entry.value.node.recordNamedParameterNotSupplied(_guards, _graph,
-          NamedParameterNotSuppliedOrigin(source, node.offset));
+      entry.value.node.recordNamedParameterNotSupplied(
+          _guards, _graph, NamedParameterNotSuppliedOrigin(source, node));
     }
     return calleeType.returnType;
   }
@@ -2012,7 +2085,7 @@
   NullabilityNode _nullabilityNodeForGLB(
       AstNode astNode, NullabilityNode leftNode, NullabilityNode rightNode) {
     var node = NullabilityNode.forGLB();
-    var origin = GreatestLowerBoundOrigin(source, astNode.offset);
+    var origin = GreatestLowerBoundOrigin(source, astNode);
     _graph.connect(leftNode, node, origin, guards: [rightNode]);
     _graph.connect(node, leftNode, origin);
     _graph.connect(node, rightNode, origin);
@@ -2127,12 +2200,50 @@
       return;
     }
     if (destinationType.isDartAsyncFutureOr) {
+      var s1 = destination.typeArguments[0];
+      if (sourceType.isDartAsyncFutureOr) {
+        // This is a special case not in the subtyping spec.  The subtyping spec
+        // covers this case by expanding the LHS first, which is fine but
+        // leads to redundant edges (which might be confusing for users)
+        // if T0 is FutureOr<S0> then:
+        // - T0 <: T1 iff Future<S0> <: T1 and S0 <: T1
+        // Since T1 is FutureOr<S1>, this is equivalent to:
+        // - T0 <: T1 iff (Future<S0> <: Future<S1> or Future<S0> <: S1) and
+        //                (S0 <: Future<S1> or S0 <: S1)
+        // Which is equivalent to:
+        // - T0 <: T1 iff (S0 <: S1 or Future<S0> <: S1) and
+        //                (S0 <: Future<S1> or S0 <: S1)
+        // Which is equivalent to (distributing the "and"):
+        // - T0 <: T1 iff (S0 <: S1 and (S0 <: Future<S1> or S0 <: S1)) or
+        //                (Future<S0> <: S1 and (S0 <: Future<S1> or S0 <: S1))
+        // Which is equivalent to (distributing the "and"s):
+        // - T0 <: T1 iff (S0 <: S1 and S0 <: Future<S1>) or
+        //                (S0 <: S1 and S0 <: S1) or
+        //                (Future<S0> <: S1 and S0 <: Future<S1>) or
+        //                (Future<S0> <: S1 and S0 <: S1)
+        // If S0 <: S1, the relation is satisfied.  Otherwise the only term that
+        // matters is (Future<S0> <: S1 and S0 <: Future<S1>), so this is
+        // equivalent to:
+        // - T0 <: T1 iff S0 <: S1 or (Future<S0> <: S1 and S0 <: Future<S1>)
+        // Let's consider whether there are any cases where the RHS of this "or"
+        // can be satisfied but not the LHS.  That is, assume that
+        // Future<S0> <: S1 and S0 <: Future<S1> hold, but not S0 <: S1.  S1
+        // must not be a top type (otherwise S0 <: S1 would hold), so the only
+        // way Future<S0> <: S1 can hold is if S1 is Future<A> or FutureOr<A>
+        // for some A.  In either case, Future<S1> simplifies to Future<A>, so
+        // we know that S0 <: Future<A>.  Also, in either case, Future<A> <: S1.
+        // Combining these, we have that S0 <: S1, contradicting our assumption.
+        // So the RHS of the "or" is redundant, and we can simplify to:
+        // - S0 <: S1.
+        var s0 = source.typeArguments[0];
+        _checkAssignment(origin, source: s0, destination: s1, hard: false);
+        return;
+      }
       // (From the subtyping spec):
       // if T1 is FutureOr<S1> then T0 <: T1 iff any of the following hold:
       // - either T0 <: Future<S1>
-      var s1 = destination.typeArguments[0];
       if (_typeSystem.isSubtypeOf(
-          sourceType, _typeProvider.futureType.instantiate([s1.type]))) {
+          sourceType, _typeProvider.futureType2(s1.type))) {
         // E.g. FutureOr<int> = (... as Future<int>)
         // This is handled by the InterfaceType logic below, since we treat
         // FutureOr as a supertype of Future.
@@ -2229,14 +2340,6 @@
   DecoratedType _getTypeParameterTypeBound(DecoratedType type);
 }
 
-class _CompoundOperatorInfo {
-  final MethodElement method;
-  final int offset;
-  final DartType undecoratedType;
-
-  _CompoundOperatorInfo(this.method, this.offset, this.undecoratedType);
-}
-
 /// Information about a binary expression whose boolean value could possibly
 /// affect nullability analysis.
 class _ConditionInfo {
diff --git a/pkg/nnbd_migration/lib/src/edge_origin.dart b/pkg/nnbd_migration/lib/src/edge_origin.dart
index efc646b..27db686 100644
--- a/pkg/nnbd_migration/lib/src/edge_origin.dart
+++ b/pkg/nnbd_migration/lib/src/edge_origin.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/ast/ast.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:nnbd_migration/instrumentation.dart';
 
 /// Edge origin resulting from the use of a type that is always nullable.
 ///
@@ -12,40 +14,51 @@
 /// this class is used for the edge connecting `always` to the type of f's `x`
 /// parameter, due to the fact that the `dynamic` type is always considered
 /// nullable.
-class AlwaysNullableTypeOrigin extends EdgeOriginWithLocation {
-  AlwaysNullableTypeOrigin(Source source, int offset) : super(source, offset);
+class AlwaysNullableTypeOrigin extends EdgeOrigin {
+  AlwaysNullableTypeOrigin(Source source, AstNode node) : super(source, node);
 }
 
 /// Edge origin resulting from the use of a value on the LHS of a compound
 /// assignment.
-class CompoundAssignmentOrigin extends EdgeOriginWithLocation {
-  CompoundAssignmentOrigin(Source source, int offset) : super(source, offset);
+class CompoundAssignmentOrigin extends EdgeOrigin {
+  CompoundAssignmentOrigin(Source source, AssignmentExpression node)
+      : super(source, node);
+
+  @override
+  AssignmentExpression get node => super.node as AssignmentExpression;
 }
 
 /// Common interface for classes providing information about how an edge came
 /// to be; that is, what was found in the source code that led the migration
 /// tool to create the edge.
-abstract class EdgeOrigin {
-  const EdgeOrigin();
-}
-
-/// Common base class for edge origins that are associated with a single
-/// location in the source code.
-abstract class EdgeOriginWithLocation extends EdgeOrigin {
-  /// The source file containing the code construct that led to the edge.
+abstract class EdgeOrigin extends EdgeOriginInfo {
+  @override
   final Source source;
 
-  /// The offset within the source file of the code construct that led to the
-  /// edge.
-  final int offset;
+  @override
+  final AstNode node;
 
-  EdgeOriginWithLocation(this.source, this.offset);
+  EdgeOrigin(this.source, this.node);
 }
 
 /// Edge origin resulting from the relationship between a field formal parameter
 /// and the corresponding field.
-class FieldFormalParameterOrigin extends EdgeOriginWithLocation {
-  FieldFormalParameterOrigin(Source source, int offset) : super(source, offset);
+class FieldFormalParameterOrigin extends EdgeOrigin {
+  FieldFormalParameterOrigin(Source source, FieldFormalParameter node)
+      : super(source, node);
+}
+
+/// Edge origin resulting from the use of an iterable type in a for-each loop.
+///
+/// For example, in the following code snippet:
+///   void f(Iterable<int> l) {
+///     for (int i in l) {}
+///   }
+///
+/// this class is used for the edge connecting the type of `l`'s `int` type
+/// parameter to the type of `i`.
+class ForEachVariableOrigin extends EdgeOrigin {
+  ForEachVariableOrigin(Source source, ForEachParts node) : super(source, node);
 }
 
 /// Edge origin resulting from the use of greatest lower bound.
@@ -57,13 +70,13 @@
 /// the `int` in the return type is nullable if both the `int`s in the types of
 /// `x` and `y` are nullable, due to the fact that the `int` in the return type
 /// is the greatest lower bound of the two other `int`s.
-class GreatestLowerBoundOrigin extends EdgeOriginWithLocation {
-  GreatestLowerBoundOrigin(Source source, int offset) : super(source, offset);
+class GreatestLowerBoundOrigin extends EdgeOrigin {
+  GreatestLowerBoundOrigin(Source source, AstNode node) : super(source, node);
 }
 
 /// Edge origin resulting from the presence of a `??` operator.
-class IfNullOrigin extends EdgeOriginWithLocation {
-  IfNullOrigin(Source source, int offset) : super(source, offset);
+class IfNullOrigin extends EdgeOrigin {
+  IfNullOrigin(Source source, AstNode node) : super(source, node);
 }
 
 /// Edge origin resulting from the implicit call from a mixin application
@@ -79,19 +92,20 @@
 /// this class is used for the edge connecting the types of the `i` parameters
 /// between the implicit constructor for `D` and the explicit constructor for
 /// `C`.
-class ImplicitMixinSuperCallOrigin extends EdgeOriginWithLocation {
-  ImplicitMixinSuperCallOrigin(Source source, int offset)
-      : super(source, offset);
+class ImplicitMixinSuperCallOrigin extends EdgeOrigin {
+  ImplicitMixinSuperCallOrigin(Source source, ClassTypeAlias node)
+      : super(source, node);
 }
 
 /// Edge origin resulting from an inheritance relationship between two methods.
-class InheritanceOrigin extends EdgeOriginWithLocation {
-  InheritanceOrigin(Source source, int offset) : super(source, offset);
+class InheritanceOrigin extends EdgeOrigin {
+  InheritanceOrigin(Source source, AstNode node) : super(source, node);
 }
 
 /// Edge origin resulting from a type that is inferred from its initializer.
-class InitializerInferenceOrigin extends EdgeOriginWithLocation {
-  InitializerInferenceOrigin(Source source, int offset) : super(source, offset);
+class InitializerInferenceOrigin extends EdgeOrigin {
+  InitializerInferenceOrigin(Source source, VariableDeclaration node)
+      : super(source, node);
 }
 
 /// Edge origin resulting from a class that is instantiated to bounds.
@@ -102,8 +116,29 @@
 ///
 /// this class is used for the edge connecting the type of x's type parameter
 /// with the type bound in the declaration of C.
-class InstantiateToBoundsOrigin extends EdgeOriginWithLocation {
-  InstantiateToBoundsOrigin(Source source, int offset) : super(source, offset);
+class InstantiateToBoundsOrigin extends EdgeOrigin {
+  InstantiateToBoundsOrigin(Source source, TypeName node) : super(source, node);
+}
+
+/// Edge origin resulting from the use of a type as a component type in an 'is'
+/// check.
+///
+/// Somewhat opposite of the principle type, allowing improper non-null type
+/// parameters etc. in an is check (`is List<int>` instead of `is List<int?>`)
+/// could introduce a change to runtime behavior.
+class IsCheckComponentTypeOrigin extends EdgeOrigin {
+  IsCheckComponentTypeOrigin(Source source, TypeAnnotation node)
+      : super(source, node);
+}
+
+/// Edge origin resulting from the use of a type as the main type in an 'is'
+/// check.
+///
+/// Before the migration, there was no way to say `is int?`, and therefore,
+// `is int` should migrate to non-null int.
+class IsCheckMainTypeOrigin extends EdgeOrigin {
+  IsCheckMainTypeOrigin(Source source, TypeAnnotation node)
+      : super(source, node);
 }
 
 /// Edge origin resulting from a call site that does not supply a named
@@ -118,9 +153,9 @@
 /// this class is used for the edge connecting `always` to the type of f's `i`
 /// parameter, due to the fact that the call to `f` implicitly passes a null
 /// value for `i`.
-class NamedParameterNotSuppliedOrigin extends EdgeOriginWithLocation {
-  NamedParameterNotSuppliedOrigin(Source source, int offset)
-      : super(source, offset);
+class NamedParameterNotSuppliedOrigin extends EdgeOrigin {
+  NamedParameterNotSuppliedOrigin(Source source, AstNode node)
+      : super(source, node);
 }
 
 /// Edge origin resulting from the presence of a non-null assertion.
@@ -132,8 +167,8 @@
 ///
 /// this class is used for the edge connecting the type of f's `i` parameter to
 /// `never`, due to the assert statement proclaiming that `i` is not `null`.
-class NonNullAssertionOrigin extends EdgeOriginWithLocation {
-  NonNullAssertionOrigin(Source source, int offset) : super(source, offset);
+class NonNullAssertionOrigin extends EdgeOrigin {
+  NonNullAssertionOrigin(Source source, Assertion node) : super(source, node);
 }
 
 /// Edge origin resulting from the presence of an explicit nullability hint
@@ -144,8 +179,9 @@
 ///
 /// this class is used for the edge connecting `always` to the type of f's `i`
 /// parameter, due to the presence of the `/*?*/` comment.
-class NullabilityCommentOrigin extends EdgeOriginWithLocation {
-  NullabilityCommentOrigin(Source source, int offset) : super(source, offset);
+class NullabilityCommentOrigin extends EdgeOrigin {
+  NullabilityCommentOrigin(Source source, TypeAnnotation node)
+      : super(source, node);
 }
 
 /// Edge origin resulting from the presence of an optional formal parameter.
@@ -155,7 +191,7 @@
 ///
 /// this class is used for the edge connecting `always` to the type of f's `i`
 /// parameter, due to the fact that `i` is optional and has no initializer.
-class OptionalFormalParameterOrigin extends EdgeOriginWithLocation {
-  OptionalFormalParameterOrigin(Source source, int offset)
-      : super(source, offset);
+class OptionalFormalParameterOrigin extends EdgeOrigin {
+  OptionalFormalParameterOrigin(Source source, DefaultFormalParameter node)
+      : super(source, node);
 }
diff --git a/pkg/nnbd_migration/lib/src/expression_checks.dart b/pkg/nnbd_migration/lib/src/expression_checks.dart
index fd87c85..1dffb8d 100644
--- a/pkg/nnbd_migration/lib/src/expression_checks.dart
+++ b/pkg/nnbd_migration/lib/src/expression_checks.dart
@@ -2,7 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:nnbd_migration/instrumentation.dart';
+import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:nnbd_migration/src/edge_origin.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
 import 'package:nnbd_migration/src/potential_modification.dart';
@@ -15,7 +19,7 @@
 /// based on the nullability of the type itself (which can be checked by adding
 /// a trailing `!`) from checks based on type parameters (which will have to be
 /// checked using an `as` expression).
-class ExpressionChecks extends PotentialModification implements EdgeOrigin {
+class ExpressionChecks extends PotentialModification {
   /// Source offset where a trailing `!` might need to be inserted.
   final int offset;
 
@@ -42,6 +46,10 @@
   ExpressionChecks(this.offset);
 
   @override
+  NullabilityFixDescription get description =>
+      NullabilityFixDescription.checkExpression;
+
+  @override
   bool get isEmpty {
     for (var edge in edges) {
       if (!edge.isSatisfied) return false;
@@ -58,4 +66,22 @@
     // reified to contain only non-null ints.
     return isEmpty ? [] : [SourceEdit(offset, 0, '!')];
   }
+
+  @override
+  Iterable<FixReasonInfo> get reasons sync* {
+    for (var edge in edges) {
+      if (!edge.isSatisfied) yield edge;
+    }
+  }
+}
+
+/// [EdgeOrigin] object associated with [ExpressionChecks].  This is a separate
+/// object so that it can safely store a pointer to an AST node.  (We don't want
+/// to store pointers to AST nodes in [ExpressionChecks] objects because they
+/// are persisted for the duration of the migration calculation).
+class ExpressionChecksOrigin extends EdgeOrigin {
+  final ExpressionChecks checks;
+
+  ExpressionChecksOrigin(Source source, Expression node, this.checks)
+      : super(source, node);
 }
diff --git a/pkg/nnbd_migration/lib/src/node_builder.dart b/pkg/nnbd_migration/lib/src/node_builder.dart
index 01061d1..1f5d917 100644
--- a/pkg/nnbd_migration/lib/src/node_builder.dart
+++ b/pkg/nnbd_migration/lib/src/node_builder.dart
@@ -5,6 +5,7 @@
 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/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/handle.dart';
 import 'package:analyzer/src/dart/element/type.dart';
@@ -12,6 +13,7 @@
 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';
 import 'package:nnbd_migration/src/conditional_discard.dart';
 import 'package:nnbd_migration/src/decorated_type.dart';
@@ -56,6 +58,8 @@
 
   final NullabilityMigrationListener /*?*/ listener;
 
+  final NullabilityMigrationInstrumentation /*?*/ instrumentation;
+
   final NullabilityGraph _graph;
 
   final TypeProvider _typeProvider;
@@ -70,7 +74,8 @@
   final DecoratedType _nonNullableStackTraceType;
 
   NodeBuilder(this._variables, this.source, this.listener, this._graph,
-      this._typeProvider)
+      this._typeProvider,
+      {this.instrumentation})
       : _dynamicType = DecoratedType(_typeProvider.dynamicType, _graph.always),
         _nonNullableObjectType =
             DecoratedType(_typeProvider.objectType, _graph.never),
@@ -82,14 +87,21 @@
     DecoratedType exceptionType = node.exceptionType?.accept(this);
     if (node.exceptionParameter != null) {
       // If there is no `on Type` part of the catch clause, the type is dynamic.
-      exceptionType ??= _dynamicType;
+      if (exceptionType == null) {
+        exceptionType = _dynamicType;
+        instrumentation?.implicitType(
+            source, node.exceptionParameter, exceptionType);
+      }
       _variables.recordDecoratedElementType(
           node.exceptionParameter.staticElement, exceptionType);
     }
     if (node.stackTraceParameter != null) {
       // The type of stack traces is always StackTrace (non-nullable).
+      var stackTraceType = _nonNullableStackTraceType;
       _variables.recordDecoratedElementType(
-          node.stackTraceParameter.staticElement, _nonNullableStackTraceType);
+          node.stackTraceParameter.staticElement, stackTraceType);
+      instrumentation?.implicitType(
+          source, node.stackTraceParameter, stackTraceType);
     }
     node.stackTraceParameter?.accept(this);
     node.body?.accept(this);
@@ -152,6 +164,7 @@
   @override
   DecoratedType visitConstructorDeclaration(ConstructorDeclaration node) {
     _handleExecutableDeclaration(
+        node,
         node.declaredElement,
         node.metadata,
         null,
@@ -168,11 +181,13 @@
     node.metadata.accept(this);
     DecoratedType type = node.type?.accept(this);
     if (node.identifier != null) {
+      if (type == null) {
+        type = DecoratedType.forImplicitType(
+            _typeProvider, node.declaredElement.type, _graph);
+        instrumentation?.implicitType(source, node, type);
+      }
       _variables.recordDecoratedElementType(
-          node.identifier.staticElement,
-          type ??
-              DecoratedType.forImplicitType(
-                  _typeProvider, node.declaredElement.type, _graph));
+          node.identifier.staticElement, type);
     }
     return type;
   }
@@ -204,6 +219,7 @@
   @override
   DecoratedType visitFunctionDeclaration(FunctionDeclaration node) {
     _handleExecutableDeclaration(
+        node,
         node.declaredElement,
         node.metadata,
         node.returnType,
@@ -217,7 +233,7 @@
 
   @override
   DecoratedType visitFunctionExpression(FunctionExpression node) {
-    _handleExecutableDeclaration(node.declaredElement, null, null,
+    _handleExecutableDeclaration(node, node.declaredElement, null, null,
         node.typeParameters, node.parameters, null, node.body, null);
     return null;
   }
@@ -235,6 +251,7 @@
       // Inferred return type.
       decoratedReturnType = DecoratedType.forImplicitType(
           _typeProvider, functionType.returnType, _graph);
+      instrumentation?.implicitReturnType(source, node, decoratedReturnType);
     }
     var previousPositionalParameters = _positionalParameters;
     var previousNamedParameters = _namedParameters;
@@ -291,6 +308,7 @@
   @override
   DecoratedType visitMethodDeclaration(MethodDeclaration node) {
     _handleExecutableDeclaration(
+        node,
         node.declaredElement,
         node.metadata,
         node.returnType,
@@ -325,7 +343,7 @@
     if (type.isVoid || type.isDynamic) {
       var nullabilityNode = NullabilityNode.forTypeAnnotation(node.end);
       _graph.connect(_graph.always, nullabilityNode,
-          AlwaysNullableTypeOrigin(source, node.offset));
+          AlwaysNullableTypeOrigin(source, node));
       var decoratedType = DecoratedType(type, nullabilityNode);
       _variables.recordDecoratedTypeAnnotation(
           source, node, decoratedType, null);
@@ -343,6 +361,7 @@
               .map((t) =>
                   DecoratedType.forImplicitType(_typeProvider, t, _graph))
               .toList();
+          instrumentation?.implicitTypeArguments(source, node, typeArguments);
         } else {
           typeArguments =
               node.typeArguments.arguments.map((t) => t.accept(this)).toList();
@@ -353,10 +372,13 @@
     }
     if (node is GenericFunctionType) {
       var returnType = node.returnType;
-      decoratedReturnType = returnType == null
-          ? DecoratedType.forImplicitType(
-              _typeProvider, DynamicTypeImpl.instance, _graph)
-          : returnType.accept(this);
+      if (returnType == null) {
+        decoratedReturnType = DecoratedType.forImplicitType(
+            _typeProvider, DynamicTypeImpl.instance, _graph);
+        instrumentation?.implicitReturnType(source, node, decoratedReturnType);
+      } else {
+        decoratedReturnType = returnType.accept(this);
+      }
       positionalParameters = <DecoratedType>[];
       namedParameters = <String, DecoratedType>{};
       typeFormalBounds = <DecoratedType>[];
@@ -411,12 +433,12 @@
     switch (_classifyComment(commentToken)) {
       case _NullabilityComment.bang:
         _graph.connect(decoratedType.node, _graph.never,
-            NullabilityCommentOrigin(source, commentToken.offset),
+            NullabilityCommentOrigin(source, node),
             hard: true);
         break;
       case _NullabilityComment.question:
         _graph.connect(_graph.always, decoratedType.node,
-            NullabilityCommentOrigin(source, commentToken.offset));
+            NullabilityCommentOrigin(source, node));
         break;
       case _NullabilityComment.none:
         break;
@@ -437,7 +459,7 @@
     } else {
       var nullabilityNode = NullabilityNode.forInferredType();
       _graph.union(_graph.always, nullabilityNode,
-          AlwaysNullableTypeOrigin(source, node.offset));
+          AlwaysNullableTypeOrigin(source, node));
       decoratedBound = DecoratedType(_typeProvider.objectType, nullabilityNode);
     }
     _typeFormalBounds?.add(decoratedBound);
@@ -453,11 +475,12 @@
     for (var variable in node.variables) {
       variable.metadata.accept(this);
       var declaredElement = variable.declaredElement;
-      _variables.recordDecoratedElementType(
-          declaredElement,
-          type ??
-              DecoratedType.forImplicitType(
-                  _typeProvider, declaredElement.type, _graph));
+      if (type == null) {
+        type = DecoratedType.forImplicitType(
+            _typeProvider, declaredElement.type, _graph);
+        instrumentation?.implicitType(source, node, type);
+      }
+      _variables.recordDecoratedElementType(declaredElement, type);
       variable.initializer?.accept(this);
     }
     return null;
@@ -474,14 +497,23 @@
   DecoratedType _createDecoratedTypeForClass(
       ClassElement classElement, AstNode node) {
     var typeArguments = classElement.typeParameters
-        .map((t) => DecoratedType(t.type, _graph.never))
+        .map((t) => t.instantiate(nullabilitySuffix: NullabilitySuffix.star))
         .toList();
-    return DecoratedType(classElement.type, _graph.never,
-        typeArguments: typeArguments);
+    var decoratedTypeArguments =
+        typeArguments.map((t) => DecoratedType(t, _graph.never)).toList();
+    return DecoratedType(
+      classElement.instantiate(
+        typeArguments: typeArguments,
+        nullabilitySuffix: NullabilitySuffix.star,
+      ),
+      _graph.never,
+      typeArguments: decoratedTypeArguments,
+    );
   }
 
   /// Common handling of function and method declarations.
   void _handleExecutableDeclaration(
+      AstNode node,
       ExecutableElement declaredElement,
       NodeList<Annotation> metadata,
       TypeAnnotation returnType,
@@ -500,10 +532,12 @@
       // implicit return type.
       decoratedReturnType = _createDecoratedTypeForClass(
           declaredElement.enclosingElement, parameters.parent);
+      instrumentation?.implicitReturnType(source, node, decoratedReturnType);
     } else {
       // Inferred return type.
       decoratedReturnType = DecoratedType.forImplicitType(
           _typeProvider, functionType.returnType, _graph);
+      instrumentation?.implicitReturnType(source, node, decoratedReturnType);
     }
     var previousPositionalParameters = _positionalParameters;
     var previousNamedParameters = _namedParameters;
@@ -541,15 +575,22 @@
     node.metadata?.accept(this);
     DecoratedType decoratedType;
     if (parameters == null) {
-      decoratedType = type != null
-          ? type.accept(this)
-          : DecoratedType.forImplicitType(
-              _typeProvider, declaredElement.type, _graph);
+      if (type != null) {
+        decoratedType = type.accept(this);
+      } else {
+        decoratedType = DecoratedType.forImplicitType(
+            _typeProvider, declaredElement.type, _graph);
+        instrumentation?.implicitType(source, node, decoratedType);
+      }
     } else {
-      var decoratedReturnType = type == null
-          ? DecoratedType.forImplicitType(
-              _typeProvider, DynamicTypeImpl.instance, _graph)
-          : type.accept(this);
+      DecoratedType decoratedReturnType;
+      if (type == null) {
+        decoratedReturnType = DecoratedType.forImplicitType(
+            _typeProvider, DynamicTypeImpl.instance, _graph);
+        instrumentation?.implicitReturnType(source, node, decoratedReturnType);
+      } else {
+        decoratedReturnType = type.accept(this);
+      }
       if (typeParameters != null) {
         // TODO(paulberry)
         _unimplemented(
@@ -707,7 +748,7 @@
 
   /// Associates a set of nullability checks with the given expression [node].
   void recordExpressionChecks(
-      Source source, Expression expression, ExpressionChecks checks);
+      Source source, Expression expression, ExpressionChecksOrigin origin);
 }
 
 /// Types of comments that can influence nullability
diff --git a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
index 53c75ec..247fee8 100644
--- a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
@@ -6,9 +6,9 @@
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:meta/meta.dart';
+import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:nnbd_migration/src/edge_builder.dart';
-import 'package:nnbd_migration/src/expression_checks.dart';
 import 'package:nnbd_migration/src/node_builder.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
 import 'package:nnbd_migration/src/potential_modification.dart';
@@ -24,6 +24,8 @@
 
   final bool _permissive;
 
+  final NullabilityMigrationInstrumentation _instrumentation;
+
   /// Prepares to perform nullability migration.
   ///
   /// If [permissive] is `true`, exception handling logic will try to proceed
@@ -31,10 +33,15 @@
   /// complete.  TODO(paulberry): remove this mode once the migration algorithm
   /// is fully implemented.
   NullabilityMigrationImpl(NullabilityMigrationListener listener,
-      {bool permissive: false})
-      : this._(listener, NullabilityGraph(), permissive);
+      {bool permissive: false,
+      NullabilityMigrationInstrumentation instrumentation})
+      : this._(listener, NullabilityGraph(instrumentation: instrumentation),
+            permissive, instrumentation);
 
-  NullabilityMigrationImpl._(this.listener, this._graph, this._permissive);
+  NullabilityMigrationImpl._(
+      this.listener, this._graph, this._permissive, this._instrumentation) {
+    _instrumentation?.immutableNodes(_graph.never, _graph.always);
+  }
 
   void finish() {
     _graph.propagate();
@@ -48,26 +55,31 @@
     // it, we can't report on every unsatisfied edge.  We need to figure out a
     // way to report unsatisfied edges that isn't too overwhelming.
     if (_variables != null) {
-      broadcast(_variables, listener);
+      broadcast(_variables, listener, _instrumentation);
     }
   }
 
   void prepareInput(ResolvedUnitResult result) {
-    _variables ??= Variables(_graph, result.typeProvider);
+    _variables ??= Variables(_graph, result.typeProvider,
+        instrumentation: _instrumentation);
     var unit = result.unit;
     unit.accept(NodeBuilder(_variables, unit.declaredElement.source,
-        _permissive ? listener : null, _graph, result.typeProvider));
+        _permissive ? listener : null, _graph, result.typeProvider,
+        instrumentation: _instrumentation));
   }
 
   void processInput(ResolvedUnitResult result) {
     var unit = result.unit;
     unit.accept(EdgeBuilder(result.typeProvider, result.typeSystem, _variables,
-        _graph, unit.declaredElement.source, _permissive ? listener : null));
+        _graph, unit.declaredElement.source, _permissive ? listener : null,
+        instrumentation: _instrumentation));
   }
 
   @visibleForTesting
   static void broadcast(
-      Variables variables, NullabilityMigrationListener listener) {
+      Variables variables,
+      NullabilityMigrationListener listener,
+      NullabilityMigrationInstrumentation instrumentation) {
     for (var entry in variables.getPotentialModifications().entries) {
       var source = entry.key;
       final lineInfo = LineInfo.fromContent(source.contents.data);
@@ -79,6 +91,7 @@
         var fix =
             _SingleNullabilityFix(source, potentialModification, lineInfo);
         listener.addFix(fix);
+        instrumentation?.fix(fix, potentialModification.reasons);
         for (var edit in modifications) {
           listener.addEdit(fix, edit);
         }
@@ -100,32 +113,6 @@
 
   factory _SingleNullabilityFix(Source source,
       PotentialModification potentialModification, LineInfo lineInfo) {
-    // TODO(paulberry): once everything is migrated into the analysis server,
-    // the migration engine can just create SingleNullabilityFix objects
-    // directly and set their kind appropriately; we won't need to translate the
-    // kinds using a bunch of `is` checks.
-    NullabilityFixDescription desc;
-    if (potentialModification is ExpressionChecks) {
-      desc = NullabilityFixDescription.checkExpression;
-    } else if (potentialModification is PotentiallyAddQuestionSuffix) {
-      desc = NullabilityFixDescription.makeTypeNullable(
-          potentialModification.type.toString());
-    } else if (potentialModification is ConditionalModification) {
-      desc = potentialModification.discard.keepFalse
-          ? NullabilityFixDescription.discardThen
-          : NullabilityFixDescription.discardElse;
-    } else if (potentialModification is PotentiallyAddImport) {
-      desc =
-          NullabilityFixDescription.addImport(potentialModification.importPath);
-    } else if (potentialModification is PotentiallyAddRequired) {
-      desc = NullabilityFixDescription.addRequired(
-          potentialModification.className,
-          potentialModification.methodName,
-          potentialModification.parameterName);
-    } else {
-      throw new UnimplementedError('TODO(paulberry)');
-    }
-
     Location location;
 
     if (potentialModification.modifications.isNotEmpty) {
@@ -140,7 +127,8 @@
       );
     }
 
-    return _SingleNullabilityFix._(source, desc, location: location);
+    return _SingleNullabilityFix._(source, potentialModification.description,
+        location: location);
   }
 
   _SingleNullabilityFix._(this.source, this.description, {Location location})
diff --git a/pkg/nnbd_migration/lib/src/nullability_node.dart b/pkg/nnbd_migration/lib/src/nullability_node.dart
index 244df1e..f0122b0 100644
--- a/pkg/nnbd_migration/lib/src/nullability_node.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_node.dart
@@ -4,6 +4,8 @@
 
 import 'package:analyzer/src/generated/source.dart';
 import 'package:meta/meta.dart';
+import 'package:nnbd_migration/instrumentation.dart';
+import 'package:nnbd_migration/nullability_state.dart';
 
 import 'edge_origin.dart';
 
@@ -11,45 +13,43 @@
 /// object to another [NullabilityNode] that is "downstream" from it (meaning
 /// that if the former node is nullable, then the latter node will either have
 /// to be nullable, or null checks will have to be added).
-class NullabilityEdge {
-  /// The node that is downstream.
+class NullabilityEdge implements EdgeInfo {
+  @override
   final NullabilityNode destinationNode;
 
-  /// A set of source nodes.  By convention, the first node is the primary
-  /// source and the other nodes are "guards".  The destination node will only
-  /// need to be made nullable if all the source nodes are nullable.
-  final List<NullabilityNode> sources;
+  /// A set of upstream nodes.  By convention, the first node is the source node
+  /// and the other nodes are "guards".  The destination node will only need to
+  /// be made nullable if all the upstream nodes are nullable.
+  final List<NullabilityNode> upstreamNodes;
 
   final _NullabilityEdgeKind _kind;
 
-  /// An [EdgeOrigin] object indicating what was found in the source code that
-  /// caused the edge to be generated.
-  final EdgeOrigin origin;
+  NullabilityEdge._(this.destinationNode, this.upstreamNodes, this._kind);
 
-  NullabilityEdge._(
-      this.destinationNode, this.sources, this._kind, this.origin);
+  @override
+  Iterable<NullabilityNode> get guards => upstreamNodes.skip(1);
 
-  Iterable<NullabilityNode> get guards => sources.skip(1);
+  @override
+  bool get isHard => _kind != _NullabilityEdgeKind.soft;
 
-  bool get hard => _kind != _NullabilityEdgeKind.soft;
-
-  /// Indicates whether nullability was successfully propagated through this
-  /// edge.
+  @override
   bool get isSatisfied {
     if (!_isTriggered) return true;
     return destinationNode.isNullable;
   }
 
+  @override
   bool get isUnion => _kind == _NullabilityEdgeKind.union;
 
-  NullabilityNode get primarySource => sources.first;
+  @override
+  NullabilityNode get sourceNode => upstreamNodes.first;
 
-  /// Indicates whether all the sources of this edge are nullable (and thus
-  /// downstream nullability propagation should try to make the destination node
-  /// nullable, if possible).
+  /// Indicates whether all the upstream nodes of this edge are nullable (and
+  /// thus downstream nullability propagation should try to make the destination
+  /// node nullable, if possible).
   bool get _isTriggered {
-    for (var source in sources) {
-      if (!source.isNullable) return false;
+    for (var upstreamNode in upstreamNodes) {
+      if (!upstreamNode.isNullable) return false;
     }
     return true;
   }
@@ -70,7 +70,7 @@
     edgeDecorations.addAll(guards);
     var edgeDecoration =
         edgeDecorations.isEmpty ? '' : '-(${edgeDecorations.join(', ')})';
-    return '$primarySource $edgeDecoration-> $destinationNode';
+    return '$sourceNode $edgeDecoration-> $destinationNode';
   }
 }
 
@@ -85,9 +85,11 @@
   /// propagation.
   static const _debugAfterPropagation = false;
 
+  final NullabilityMigrationInstrumentation /*?*/ instrumentation;
+
   /// Set containing all [NullabilityNode]s that have been passed as the
-  /// `sourceNode` argument to [connect].
-  final _allSourceNodes = Set<NullabilityNode>.identity();
+  /// `upstreamNode` argument to [connect].
+  final _allUpstreamNodes = Set<NullabilityNode>.identity();
 
   /// Returns a [NullabilityNode] that is a priori nullable.
   ///
@@ -124,6 +126,8 @@
   /// nodes that have not yet been resolved.
   List<NullabilityNodeForSubstitution> _pendingSubstitutions = [];
 
+  NullabilityGraph({this.instrumentation});
+
   /// After calling [propagate], this getter may be queried to access the set of
   /// edges that could not be satisfied.
   Iterable<NullabilityEdge> get unsatisfiedEdges => _unsatisfiedEdges;
@@ -139,9 +143,9 @@
   NullabilityEdge connect(NullabilityNode sourceNode,
       NullabilityNode destinationNode, EdgeOrigin origin,
       {bool hard: false, List<NullabilityNode> guards: const []}) {
-    var sources = [sourceNode]..addAll(guards);
+    var upstreamNodes = [sourceNode]..addAll(guards);
     var kind = hard ? _NullabilityEdgeKind.hard : _NullabilityEdgeKind.soft;
-    return _connect(sources, destinationNode, kind, origin);
+    return _connect(upstreamNodes, destinationNode, kind, origin);
   }
 
   /// Determine if [source] is in the code being migrated.
@@ -171,45 +175,46 @@
   }
 
   NullabilityEdge _connect(
-      List<NullabilityNode> sources,
+      List<NullabilityNode> upstreamNodes,
       NullabilityNode destinationNode,
       _NullabilityEdgeKind kind,
       EdgeOrigin origin) {
-    var edge = NullabilityEdge._(destinationNode, sources, kind, origin);
-    for (var source in sources) {
-      _connectDownstream(source, edge);
+    var edge = NullabilityEdge._(destinationNode, upstreamNodes, kind);
+    instrumentation?.graphEdge(edge, origin);
+    for (var upstreamNode in upstreamNodes) {
+      _connectDownstream(upstreamNode, edge);
     }
     destinationNode._upstreamEdges.add(edge);
     return edge;
   }
 
-  void _connectDownstream(NullabilityNode source, NullabilityEdge edge) {
-    _allSourceNodes.add(source);
-    source._downstreamEdges.add(edge);
-    if (source is _NullabilityNodeCompound) {
-      for (var component in source._components) {
+  void _connectDownstream(NullabilityNode upstreamNode, NullabilityEdge edge) {
+    _allUpstreamNodes.add(upstreamNode);
+    upstreamNode._downstreamEdges.add(edge);
+    if (upstreamNode is _NullabilityNodeCompound) {
+      for (var component in upstreamNode._components) {
         _connectDownstream(component, edge);
       }
     }
   }
 
   void _debugDump() {
-    for (var source in _allSourceNodes) {
-      var edges = source._downstreamEdges;
+    for (var upstreamNode in _allUpstreamNodes) {
+      var edges = upstreamNode._downstreamEdges;
       var destinations =
-          edges.where((edge) => edge.primarySource == source).map((edge) {
+          edges.where((edge) => edge.sourceNode == upstreamNode).map((edge) {
         var suffixes = <Object>[];
         if (edge.isUnion) {
           suffixes.add('union');
-        } else if (edge.hard) {
+        } else if (edge.isHard) {
           suffixes.add('hard');
         }
         suffixes.addAll(edge.guards);
         var suffix = suffixes.isNotEmpty ? ' (${suffixes.join(', ')})' : '';
         return '${edge.destinationNode}$suffix';
       });
-      var state = source._state;
-      print('$source ($state) -> ${destinations.join(', ')}');
+      var state = upstreamNode._state;
+      print('$upstreamNode ($state) -> ${destinations.join(', ')}');
     }
   }
 
@@ -220,13 +225,15 @@
     while (_pendingEdges.isNotEmpty) {
       var edge = _pendingEdges.removeLast();
       if (!edge.isUnion) continue;
-      // Union edges always have exactly one source, so we don't need to check
-      // whether all sources are nullable.
-      assert(edge.sources.length == 1);
+      // Union edges always have exactly one upstream node, so we don't need to
+      // check whether all upstream nodes are nullable.
+      assert(edge.upstreamNodes.length == 1);
       var node = edge.destinationNode;
       if (node is NullabilityNodeMutable && !node.isNullable) {
         _unionedWithAlways.add(node);
-        node._state = _NullabilityState.ordinaryNullable;
+        _setState(_PropagationStep(
+            node, NullabilityState.ordinaryNullable, StateChangeReason.union,
+            edge: edge));
         // Was not previously nullable, so we need to propagate.
         _pendingEdges.addAll(node._downstreamEdges);
       }
@@ -244,14 +251,16 @@
         var edge = _pendingEdges.removeLast();
         if (!edge._isTriggered) continue;
         var node = edge.destinationNode;
-        if (node._state == _NullabilityState.nonNullable) {
+        if (node._state == NullabilityState.nonNullable) {
           // The node has already been marked as non-nullable, so the edge can't
           // be satisfied.
           _unsatisfiedEdges.add(edge);
           continue;
         }
         if (node is NullabilityNodeMutable && !node.isNullable) {
-          _setNullable(node);
+          _setNullable(_PropagationStep(node, NullabilityState.ordinaryNullable,
+              StateChangeReason.downstream,
+              edge: edge));
         }
       }
       if (_pendingSubstitutions.isEmpty) break;
@@ -270,11 +279,13 @@
     _pendingEdges.addAll(never._upstreamEdges);
     while (_pendingEdges.isNotEmpty) {
       var edge = _pendingEdges.removeLast();
-      if (!edge.hard) continue;
-      var node = edge.primarySource;
+      if (!edge.isHard) continue;
+      var node = edge.sourceNode;
       if (node is NullabilityNodeMutable &&
-          node._state == _NullabilityState.undetermined) {
-        node._state = _NullabilityState.nonNullable;
+          node._state == NullabilityState.undetermined) {
+        _setState(_PropagationStep(
+            node, NullabilityState.nonNullable, StateChangeReason.upstream,
+            edge: edge));
         // Was not previously in the set of non-null intent nodes, so we need to
         // propagate.
         _pendingEdges.addAll(node._upstreamEdges);
@@ -288,8 +299,8 @@
     // If both nodes pointed to by the substitution node are in the non-nullable
     // state, then no resolution is needed; the substitution node can’t be
     // satisfied.
-    if (substitutionNode.innerNode._state == _NullabilityState.nonNullable &&
-        substitutionNode.outerNode._state == _NullabilityState.nonNullable) {
+    if (substitutionNode.innerNode._state == NullabilityState.nonNullable &&
+        substitutionNode.outerNode._state == NullabilityState.nonNullable) {
       _unsatisfiedSubstitutions.add(substitutionNode);
       return;
     }
@@ -302,8 +313,12 @@
 
     // Otherwise, if the inner node is in the non-nullable state, then we set
     // the outer node to the ordinary nullable state.
-    if (substitutionNode.innerNode._state == _NullabilityState.nonNullable) {
-      _setNullable(substitutionNode.outerNode as NullabilityNodeMutable);
+    if (substitutionNode.innerNode._state == NullabilityState.nonNullable) {
+      _setNullable(_PropagationStep(
+          substitutionNode.outerNode as NullabilityNodeMutable,
+          NullabilityState.ordinaryNullable,
+          StateChangeReason.substituteOuter,
+          substitutionNode: substitutionNode));
       return;
     }
 
@@ -312,28 +327,43 @@
     // rule: if there is an edge A → B, where A is in the undetermined or
     // ordinary nullable state, and B is in the exact nullable state, then A’s
     // state is changed to exact nullable.
-    var pendingNodes = [substitutionNode.innerNode];
-    while (pendingNodes.isNotEmpty) {
-      var node = pendingNodes.removeLast();
+    var pendingEdges = <NullabilityEdge>[];
+    var node = substitutionNode.innerNode;
+    if (node is NullabilityNodeMutable) {
+      var oldState = _setNullable(_PropagationStep(node,
+          NullabilityState.exactNullable, StateChangeReason.substituteInner,
+          substitutionNode: substitutionNode));
+      if (oldState != NullabilityState.exactNullable) {
+        // Was not previously in the "exact nullable" state.  Need to
+        // propagate.
+        for (var edge in node._upstreamEdges) {
+          pendingEdges.add(edge);
+        }
+      }
+    }
+    while (pendingEdges.isNotEmpty) {
+      var edge = pendingEdges.removeLast();
+      var node = edge.sourceNode;
       if (node is NullabilityNodeMutable) {
-        var oldState =
-            _setNullable(node, newState: _NullabilityState.exactNullable);
-        if (oldState != _NullabilityState.exactNullable) {
+        var oldState = _setNullable(_PropagationStep(node,
+            NullabilityState.exactNullable, StateChangeReason.exactUpstream,
+            edge: edge));
+        if (oldState != NullabilityState.exactNullable) {
           // Was not previously in the "exact nullable" state.  Need to
           // propagate.
           for (var edge in node._upstreamEdges) {
-            pendingNodes.add(edge.primarySource);
+            pendingEdges.add(edge);
           }
         }
       }
     }
   }
 
-  _NullabilityState _setNullable(NullabilityNodeMutable node,
-      {_NullabilityState newState = _NullabilityState.ordinaryNullable}) {
-    assert(newState.isNullable);
+  NullabilityState _setNullable(_PropagationStep propagationStep) {
+    var node = propagationStep.node;
+    assert(propagationStep.newState.isNullable);
     var oldState = node._state;
-    node._state = newState;
+    _setState(propagationStep);
     if (!oldState.isNullable) {
       // Was not previously nullable, so we need to propagate.
       _pendingEdges.addAll(node._downstreamEdges);
@@ -343,6 +373,11 @@
     }
     return oldState;
   }
+
+  void _setState(_PropagationStep propagationStep) {
+    propagationStep.node._state = propagationStep.newState;
+    instrumentation?.propagationStep(propagationStep);
+  }
 }
 
 /// Same as [NullabilityGraph], but extended with extra methods for easier
@@ -351,6 +386,8 @@
 class NullabilityGraphForTesting extends NullabilityGraph {
   final List<NullabilityEdge> _allEdges = [];
 
+  final Map<NullabilityEdge, EdgeOrigin> _edgeOrigins = {};
+
   /// Prints out a representation of the graph nodes.  Useful in debugging
   /// broken tests.
   void debugDump() {
@@ -363,14 +400,19 @@
     return _allEdges;
   }
 
+  /// Retrieves the [EdgeOrigin] object that was used to create [edge].
+  @visibleForTesting
+  EdgeOrigin getEdgeOrigin(NullabilityEdge edge) => _edgeOrigins[edge];
+
   @override
   NullabilityEdge _connect(
-      List<NullabilityNode> sources,
+      List<NullabilityNode> upstreamNodes,
       NullabilityNode destinationNode,
       _NullabilityEdgeKind kind,
       EdgeOrigin origin) {
-    var edge = super._connect(sources, destinationNode, kind, origin);
+    var edge = super._connect(upstreamNodes, destinationNode, kind, origin);
     _allEdges.add(edge);
+    _edgeOrigins[edge] = origin;
     return edge;
   }
 }
@@ -381,7 +423,7 @@
 /// nullability inference graph is encoded into the wrapped constraint
 /// variables.  Over time this will be replaced by a first class representation
 /// of the nullability inference graph.
-abstract class NullabilityNode {
+abstract class NullabilityNode implements NullabilityNodeInfo {
   static final _debugNamesInUse = Set<String>();
 
   bool _isPossiblyOptional = false;
@@ -451,6 +493,7 @@
 
   /// After nullability propagation, this getter can be used to query whether
   /// the type associated with this node should be considered nullable.
+  @override
   bool get isNullable;
 
   /// Indicates whether this node is associated with a named parameter for which
@@ -459,7 +502,7 @@
 
   String get _debugPrefix;
 
-  _NullabilityState get _state;
+  NullabilityState get _state;
 
   /// Records the fact that an invocation was made to a function with named
   /// parameters, and the named parameter associated with this node was not
@@ -520,19 +563,12 @@
 
 /// Derived class for nullability nodes that arise from type variable
 /// substitution.
-class NullabilityNodeForSubstitution extends _NullabilityNodeCompound {
-  /// Nullability node representing the inner type of the substitution.
-  ///
-  /// For example, if this NullabilityNode arose from substituting `int*` for
-  /// `T` in the type `T*`, [innerNode] is the nullability corresponding to the
-  /// `*` in `int*`.
+class NullabilityNodeForSubstitution extends _NullabilityNodeCompound
+    implements SubstitutionNodeInfo {
+  @override
   final NullabilityNode innerNode;
 
-  /// Nullability node representing the outer type of the substitution.
-  ///
-  /// For example, if this NullabilityNode arose from substituting `int*` for
-  /// `T` in the type `T*`, [innerNode] is the nullability corresponding to the
-  /// `*` in `T*`.
+  @override
   final NullabilityNode outerNode;
 
   NullabilityNodeForSubstitution._(this.innerNode, this.outerNode);
@@ -549,15 +585,18 @@
 /// Nearly all nullability nodes derive from this class; the only exceptions are
 /// the fixed nodes "always "never".
 abstract class NullabilityNodeMutable extends NullabilityNode {
-  _NullabilityState _state;
+  NullabilityState _state;
 
   NullabilityNodeMutable._(
-      {_NullabilityState initialState: _NullabilityState.undetermined})
+      {NullabilityState initialState: NullabilityState.undetermined})
       : _state = initialState,
         super._();
 
   @override
-  bool get isExactNullable => _state == _NullabilityState.exactNullable;
+  bool get isExactNullable => _state == NullabilityState.exactNullable;
+
+  @override
+  bool get isImmutable => false;
 
   @override
   bool get isNullable => _state.isNullable;
@@ -605,9 +644,12 @@
   bool get isExactNullable => isNullable;
 
   @override
-  _NullabilityState get _state => isNullable
-      ? _NullabilityState.exactNullable
-      : _NullabilityState.nonNullable;
+  bool get isImmutable => true;
+
+  @override
+  NullabilityState get _state => isNullable
+      ? NullabilityState.exactNullable
+      : NullabilityState.nonNullable;
 }
 
 class _NullabilityNodeSimple extends NullabilityNodeMutable {
@@ -615,39 +657,25 @@
   final String _debugPrefix;
 
   _NullabilityNodeSimple(this._debugPrefix)
-      : super._(initialState: _NullabilityState.undetermined);
+      : super._(initialState: NullabilityState.undetermined);
 }
 
-/// State of a nullability node.
-class _NullabilityState {
-  /// State of a nullability node whose nullability hasn't been decided yet.
-  static const undetermined = _NullabilityState._('undetermined', false);
-
-  /// State of a nullability node that has been determined to be non-nullable
-  /// by propagating upstream.
-  static const nonNullable = _NullabilityState._('non-nullable', false);
-
-  /// State of a nullability node that has been determined to be nullable by
-  /// propagating downstream.
-  static const ordinaryNullable =
-      _NullabilityState._('ordinary nullable', true);
-
-  /// State of a nullability node that has been determined to be nullable by
-  /// propagating upstream from a contravariant use of a generic.
-  static const exactNullable = _NullabilityState._('exact nullable', true);
-
-  /// Name of the state (for use in debugging).
-  final String name;
-
-  /// Indicates whether the given state should be considered nullable.
-  ///
-  /// After propagation, any nodes that remain in the undetermined state are
-  /// considered to be non-nullable, so this field is returns `false` for nodes
-  /// in that state.
-  final bool isNullable;
-
-  const _NullabilityState._(this.name, this.isNullable);
+class _PropagationStep implements PropagationInfo {
+  @override
+  final NullabilityNodeMutable node;
 
   @override
-  String toString() => name;
+  final NullabilityState newState;
+
+  @override
+  final StateChangeReason reason;
+
+  @override
+  final NullabilityEdge edge;
+
+  @override
+  final NullabilityNodeForSubstitution substitutionNode;
+
+  _PropagationStep(this.node, this.newState, this.reason,
+      {this.edge, this.substitutionNode});
 }
diff --git a/pkg/nnbd_migration/lib/src/potential_modification.dart b/pkg/nnbd_migration/lib/src/potential_modification.dart
index d4f13c3..ac60b15 100644
--- a/pkg/nnbd_migration/lib/src/potential_modification.dart
+++ b/pkg/nnbd_migration/lib/src/potential_modification.dart
@@ -5,6 +5,8 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart' show SourceEdit;
+import 'package:nnbd_migration/instrumentation.dart';
+import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:nnbd_migration/src/conditional_discard.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
 
@@ -44,6 +46,11 @@
       this.discard, this.condition, this.thenStatement, this.elseStatement);
 
   @override
+  NullabilityFixDescription get description => discard.keepFalse
+      ? NullabilityFixDescription.discardThen
+      : NullabilityFixDescription.discardElse;
+
+  @override
   bool get isEmpty => discard.keepTrue && discard.keepFalse;
 
   @override
@@ -81,6 +88,9 @@
     }
     return result;
   }
+
+  @override
+  Iterable<FixReasonInfo> get reasons => discard.reasons;
 }
 
 /// Records information about the possible addition of an import to the source
@@ -101,6 +111,10 @@
   }
 
   @override
+  NullabilityFixDescription get description =>
+      NullabilityFixDescription.addImport(importPath);
+
+  @override
   bool get isEmpty {
     for (PotentialModification usage in _usages) {
       if (!usage.isEmpty) {
@@ -115,6 +129,13 @@
   Iterable<SourceEdit> get modifications =>
       isEmpty ? const [] : [SourceEdit(_offset, 0, "import '$importPath';\n")];
 
+  @override
+  Iterable<FixReasonInfo> get reasons sync* {
+    for (var usage in _usages) {
+      if (!usage.isEmpty) yield* usage.reasons;
+    }
+  }
+
   void addUsage(PotentialModification usage) {
     _usages.add(usage);
   }
@@ -130,11 +151,18 @@
   PotentiallyAddQuestionSuffix(this.node, this.type, this._offset);
 
   @override
+  NullabilityFixDescription get description =>
+      NullabilityFixDescription.makeTypeNullable(type.toString());
+
+  @override
   bool get isEmpty => !node.isNullable;
 
   @override
   Iterable<SourceEdit> get modifications =>
       isEmpty ? [] : [SourceEdit(_offset, 0, '?')];
+
+  @override
+  Iterable<FixReasonInfo> get reasons => [node];
 }
 
 /// Records information about the possible addition of a `@required` annotation
@@ -160,21 +188,35 @@
       this.methodName, this.parameterName);
 
   @override
+  NullabilityFixDescription get description =>
+      NullabilityFixDescription.addRequired(
+          className, methodName, parameterName);
+
+  @override
   bool get isEmpty => _node.isNullable;
 
   @override
   Iterable<SourceEdit> get modifications =>
       isEmpty ? const [] : [SourceEdit(_offset, 0, '@required ')];
+
+  @override
+  Iterable<FixReasonInfo> get reasons => [_node];
 }
 
 /// Interface used by data structures representing potential modifications to
 /// the code being migrated.
 abstract class PotentialModification {
+  /// Gets a [NullabilityFixDescription] describing this modification.
+  NullabilityFixDescription get description;
+
   bool get isEmpty;
 
   /// Gets the individual migrations that need to be done, considering the
   /// solution to the constraint equations.
   Iterable<SourceEdit> get modifications;
+
+  /// Gets the reasons for this potential modification.
+  Iterable<FixReasonInfo> get reasons;
 }
 
 /// Helper object used by [ConditionalModification] to keep track of AST nodes
diff --git a/pkg/nnbd_migration/lib/src/variables.dart b/pkg/nnbd_migration/lib/src/variables.dart
index e1e88ee..8406cd4 100644
--- a/pkg/nnbd_migration/lib/src/variables.dart
+++ b/pkg/nnbd_migration/lib/src/variables.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/src/already_migrated_code_decorator.dart';
 import 'package:nnbd_migration/src/conditional_discard.dart';
 import 'package:nnbd_migration/src/decorated_type.dart';
@@ -33,7 +34,9 @@
 
   final AlreadyMigratedCodeDecorator _alreadyMigratedCodeDecorator;
 
-  Variables(this._graph, TypeProvider typeProvider)
+  final NullabilityMigrationInstrumentation /*?*/ instrumentation;
+
+  Variables(this._graph, TypeProvider typeProvider, {this.instrumentation})
       : _alreadyMigratedCodeDecorator =
             AlreadyMigratedCodeDecorator(_graph, typeProvider);
 
@@ -142,6 +145,7 @@
 
   void recordDecoratedTypeAnnotation(Source source, TypeAnnotation node,
       DecoratedType type, PotentiallyAddQuestionSuffix potentialModification) {
+    instrumentation?.explicitTypeNullability(source, node, type.node);
     if (potentialModification != null)
       _addPotentialModification(source, potentialModification);
     (_decoratedTypeAnnotations[source] ??=
@@ -160,8 +164,8 @@
 
   @override
   void recordExpressionChecks(
-      Source source, Expression expression, ExpressionChecks checks) {
-    _addPotentialModification(source, checks);
+      Source source, Expression expression, ExpressionChecksOrigin origin) {
+    _addPotentialModification(source, origin.checks);
   }
 
   @override
@@ -240,6 +244,7 @@
       // TODO(paulberry)
       throw UnimplementedError('Decorating ${element.runtimeType}');
     }
+    instrumentation?.externalDecoratedType(element, decoratedType);
     return decoratedType;
   }
 
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 b2b058c..7a20cc3 100644
--- a/pkg/nnbd_migration/test/already_migrated_code_decorator_test.dart
+++ b/pkg/nnbd_migration/test/already_migrated_code_decorator_test.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';
@@ -51,7 +52,7 @@
       DecoratedType decoratedType,
       NullabilityNode expectedNullability,
       void Function(DecoratedType) checkArgument) {
-    expect(decoratedType.type.element, typeProvider.futureOrType.element);
+    expect(decoratedType.type.element, typeProvider.futureOrElement);
     expect(decoratedType.node, expectedNullability);
     checkArgument(decoratedType.typeArguments[0]);
   }
@@ -215,7 +216,7 @@
   }
 
   test_getImmediateSupertypes_future() {
-    var element = typeProvider.futureType.element;
+    var element = typeProvider.futureElement;
     var decoratedSupertypes =
         decorator.getImmediateSupertypes(element).toList();
     var typeParam = element.typeParameters[0];
@@ -231,9 +232,12 @@
   test_getImmediateSupertypes_generic() {
     var t = ElementFactory.typeParameterElement('T');
     var class_ = ElementFactory.classElement3(
-        name: 'C',
-        typeParameters: [t],
-        supertype: typeProvider.iterableType.instantiate([t.type]));
+      name: 'C',
+      typeParameters: [t],
+      supertype: typeProvider.iterableType2(
+        t.instantiate(nullabilitySuffix: NullabilitySuffix.star),
+      ),
+    );
     var decoratedSupertypes = decorator.getImmediateSupertypes(class_).toList();
     expect(decoratedSupertypes, hasLength(1));
     checkIterable(decoratedSupertypes[0], never,
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index e7593d2..6b01783 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -2,14 +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:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'abstract_context.dart';
+import 'api_test_base.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -41,7 +40,7 @@
     for (var path in input.keys) {
       newFile(path, content: input[path]);
     }
-    var listener = new _TestMigrationListener();
+    var listener = new TestMigrationListener();
     var migration =
         NullabilityMigration(listener, permissive: _usePermissiveMode);
     for (var path in input.keys) {
@@ -53,7 +52,7 @@
     }
     migration.finish();
     var sourceEdits = <String, List<SourceEdit>>{};
-    for (var entry in listener._edits.entries) {
+    for (var entry in listener.edits.entries) {
       var path = entry.key.fullName;
       expect(expectedOutput.keys, contains(path));
       sourceEdits[path] = entry.value;
@@ -77,6 +76,17 @@
 
 /// Mixin containing test cases for the provisional API.
 mixin _ProvisionalApiTestCases on _ProvisionalApiTestBase {
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38461')
+  test_add_required() async {
+    var content = '''
+int f({String s}) => s.length;
+''';
+    var expected = '''
+int f({required String s}) => s.length;
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   test_assign_null_to_generic_type() async {
     var content = '''
 main() {
@@ -91,6 +101,37 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38341')
+  test_back_propagation_stops_at_implicitly_typed_variables() async {
+    var content = '''
+class C {
+  int v;
+  C(this.v);
+}
+f(C c) {
+  var x = c.v;
+  print(x + 1);
+}
+main() {
+  C(null);
+}
+''';
+    var expected = '''
+class C {
+  int? v;
+  C(this.v);
+}
+f(C c) {
+  var x = c.v!;
+  print(x + 1);
+}
+main() {
+  C(null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   test_catch_simple() async {
     var content = '''
 void f() {
@@ -439,6 +480,20 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38462')
+  test_convert_required() async {
+    addMetaPackage();
+    var content = '''
+import 'package:meta/meta.dart';
+void f({@required String s}) {}
+''';
+    var expected = '''
+import 'package:meta/meta.dart';
+void f({required String s}) {}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   test_data_flow_assignment_field() async {
     var content = '''
 class C {
@@ -878,6 +933,32 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  test_definitely_assigned_value() async {
+    var content = '''
+String f(bool b) {
+  String s;
+  if (b) {
+    s = 'true';
+  } else {
+    s = 'false';
+  }
+  return s;
+}
+''';
+    var expected = '''
+String f(bool b) {
+  String s;
+  if (b) {
+    s = 'true';
+  } else {
+    s = 'false';
+  }
+  return s;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   test_discard_simple_condition() async {
     var content = '''
 int f(int i) {
@@ -1212,6 +1293,32 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  test_for_each_basic() async {
+    var content = '''
+void f(List<int> l) {
+  for (var x in l) {
+    g(x);
+  }
+}
+void g(int x) {}
+main() {
+  f([null]);
+}
+''';
+    var expected = '''
+void f(List<int?> l) {
+  for (var x in l) {
+    g(x);
+  }
+}
+void g(int? x) {}
+main() {
+  f([null]);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   test_function_expression() async {
     var content = '''
 int f(int i) {
@@ -1629,6 +1736,32 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  test_is_promotion_implies_non_nullable() async {
+    var content = '''
+bool f(Object o) => o is int && o.isEven;
+main() {
+  f(null);
+}
+''';
+    var expected = '''
+bool f(Object? o) => o is int && o.isEven;
+main() {
+  f(null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_isExpression_typeName_typeArguments() async {
+    var content = '''
+bool f(a) => a is List<int>;
+''';
+    var expected = '''
+bool f(a) => a is List<int?>;
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   test_local_function() async {
     var content = '''
 int f(int i) {
@@ -2021,6 +2154,29 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38344')
+  test_not_definitely_assigned_value() async {
+    var content = '''
+String f(bool b) {
+  String s;
+  if (b) {
+    s = 'true';
+  }
+  return s;
+}
+''';
+    var expected = '''
+String? f(bool b) {
+  String? s;
+  if (b) {
+    s = 'true';
+  }
+  return s;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   test_null_aware_getter_invocation() async {
     var content = '''
 bool f(int i) => i?.isEven;
@@ -2097,6 +2253,25 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38339')
+  test_operator_eq_with_inferred_parameter_type() async {
+    var content = '''
+class C {
+  operator==(Object other) {
+    return other is C;
+  }
+}
+''';
+    var expected = '''
+class C {
+  operator==(Object other) {
+    return other is C;
+  }
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   test_override_parameter_type_non_nullable() async {
     var content = '''
 abstract class Base {
@@ -2918,6 +3093,27 @@
 ''';
     await _checkSingleFileChanges(content, expected);
   }
+
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38453')
+  test_unconditional_use_of_field_formal_param_does_not_create_hard_edge() async {
+    var content = '''
+class C {
+  int i;
+  int j;
+  C.one(this.i) : j = i + 1;
+  C.two() : i = null, j = 0;
+}
+''';
+    var expected = '''
+class C {
+  int? i;
+  int j;
+  C.one(this.i) : j = i! + 1;
+  C.two() : i = null, j = 0;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
 }
 
 @reflectiveTest
@@ -2947,23 +3143,3 @@
     driver.resetUriResolution();
   }
 }
-
-class _TestMigrationListener implements NullabilityMigrationListener {
-  final _edits = <Source, List<SourceEdit>>{};
-
-  List<String> details = [];
-
-  @override
-  void addEdit(SingleNullabilityFix fix, SourceEdit edit) {
-    (_edits[fix.source] ??= []).add(edit);
-  }
-
-  @override
-  void addFix(SingleNullabilityFix fix) {}
-
-  @override
-  void reportException(
-      Source source, AstNode node, Object exception, StackTrace stackTrace) {
-    fail('Exception reported: $exception');
-  }
-}
diff --git a/pkg/nnbd_migration/test/api_test_base.dart b/pkg/nnbd_migration/test/api_test_base.dart
new file mode 100644
index 0000000..f886f0d
--- /dev/null
+++ b/pkg/nnbd_migration/test/api_test_base.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.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:nnbd_migration/nnbd_migration.dart';
+import 'package:test/test.dart';
+
+class TestMigrationListener implements NullabilityMigrationListener {
+  final edits = <Source, List<SourceEdit>>{};
+
+  List<String> details = [];
+
+  @override
+  void addEdit(SingleNullabilityFix fix, SourceEdit edit) {
+    (edits[fix.source] ??= []).add(edit);
+  }
+
+  @override
+  void addFix(SingleNullabilityFix fix) {}
+
+  @override
+  void reportException(
+      Source source, AstNode node, Object exception, StackTrace stackTrace) {
+    fail('Exception reported: $exception');
+  }
+}
diff --git a/pkg/nnbd_migration/test/decorated_type_test.dart b/pkg/nnbd_migration/test/decorated_type_test.dart
index a0ea3f0..61e8b6d 100644
--- a/pkg/nnbd_migration/test/decorated_type_test.dart
+++ b/pkg/nnbd_migration/test/decorated_type_test.dart
@@ -36,7 +36,7 @@
 
   NullabilityNode get always => graph.always;
 
-  ClassElement get listElement => typeProvider.listType.element;
+  ClassElement get listElement => typeProvider.listElement;
 
   void setUp() {
     NullabilityNode.clearDebugNames();
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 3643d8a..50a4879 100644
--- a/pkg/nnbd_migration/test/edge_builder_flow_analysis_test.dart
+++ b/pkg/nnbd_migration/test/edge_builder_flow_analysis_test.dart
@@ -712,6 +712,35 @@
     assertEdge(iNode, jNode, hard: false);
   }
 
+  test_for_each_assigns_to_declared_var() async {
+    await analyze('''
+void f(Iterable<int> x) {
+  for (int i in x) {
+    g(i);
+  }
+}
+void g(int j) {}
+''');
+    var iNode = decoratedTypeAnnotation('int i').node;
+    // No edge from never to i because it is assigned before it is used.
+    assertNoEdge(never, iNode);
+  }
+
+  test_for_each_assigns_to_identifier() async {
+    await analyze('''
+void f(Iterable<int> x) {
+  int i;
+  for (i in x) {
+    g(i);
+  }
+}
+void g(int j) {}
+''');
+    var iNode = decoratedTypeAnnotation('int i').node;
+    // No edge from never to i because it is assigned before it is used.
+    assertNoEdge(never, iNode);
+  }
+
   test_for_each_cancels_promotions_for_assignments_in_body() async {
     await analyze('''
 void f(int i, int j, Iterable<Object> x) {
@@ -732,6 +761,31 @@
     assertEdge(jNode, never, hard: false);
   }
 
+  test_for_each_collection_assigns_to_declared_var() async {
+    await analyze('''
+void f(Iterable<int> x) {
+  [for (int i in x) g(i)];
+}
+void g(int j) {}
+''');
+    var iNode = decoratedTypeAnnotation('int i').node;
+    // No edge from never to i because it is assigned before it is used.
+    assertNoEdge(never, iNode);
+  }
+
+  test_for_each_collection_assigns_to_identifier() async {
+    await analyze('''
+void f(Iterable<int> x) {
+  int i;
+  [for (i in x) g(i)];
+}
+void g(int j) {}
+''');
+    var iNode = decoratedTypeAnnotation('int i').node;
+    // No edge from never to i because it is assigned before it is used.
+    assertNoEdge(never, iNode);
+  }
+
   test_for_each_collection_cancels_promotions_for_assignments_in_body() async {
     await analyze('''
 void f(int i, int j, Iterable<Object> x) {
@@ -925,6 +979,48 @@
     assertEdge(iNode, kNode, hard: true);
   }
 
+  test_is() async {
+    await analyze('''
+void f(num n) {
+  if (n is int) {
+    g(n);
+  }
+  h(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_is_not() async {
+    await analyze('''
+void f(num n) {
+  if (n is! int) {} else {
+    g(n);
+  }
+  h(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_local_function_parameters() async {
     await analyze('''
 void f() {
diff --git a/pkg/nnbd_migration/test/edge_builder_test.dart b/pkg/nnbd_migration/test/edge_builder_test.dart
index 1db66dc..e70c987 100644
--- a/pkg/nnbd_migration/test/edge_builder_test.dart
+++ b/pkg/nnbd_migration/test/edge_builder_test.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/member.dart';
@@ -173,6 +174,14 @@
     assertEdge(t1.typeArguments[0].node, t2.typeArguments[0].node, hard: false);
   }
 
+  void test_future_or_to_future_or() {
+    var t1 = futureOr(int_());
+    var t2 = futureOr(int_());
+    assign(t1, t2, hard: true);
+    assertEdge(t1.node, t2.node, hard: true);
+    assertEdge(t1.typeArguments[0].node, t2.typeArguments[0].node, hard: false);
+  }
+
   test_generic_to_dynamic() {
     var t = list(object());
     assign(t, dynamic_);
@@ -348,7 +357,7 @@
     if (node == never) return;
 
     for (var edge in getEdges(anyNode, node)) {
-      expect(edge.primarySource, never);
+      expect(edge.sourceNode, never);
     }
   }
 
@@ -357,14 +366,14 @@
   /// [expressionChecks] is the object tracking whether or not a null check is
   /// needed.
   void assertNullCheck(
-      ExpressionChecks expressionChecks, NullabilityEdge expectedEdge) {
-    expect(expressionChecks.edges, contains(expectedEdge));
+      ExpressionChecksOrigin expressionChecks, NullabilityEdge expectedEdge) {
+    expect(expressionChecks.checks.edges, contains(expectedEdge));
   }
 
   /// Gets the [ExpressionChecks] associated with the expression whose text
   /// representation is [text], or `null` if the expression has no
   /// [ExpressionChecks] associated with it.
-  ExpressionChecks checkExpression(String text) {
+  ExpressionChecksOrigin checkExpression(String text) {
     return variables.checkExpression(findNode.expression(text));
   }
 
@@ -421,6 +430,17 @@
     assertEdge(decoratedTypeAnnotation('int i').node, never, hard: true);
   }
 
+  test_assert_initializer_demonstrates_non_null_intent() async {
+    await analyze('''
+class C {
+  C(int i)
+    : assert(i != null);
+}
+''');
+
+    assertEdge(decoratedTypeAnnotation('int i').node, never, hard: true);
+  }
+
   test_assign_bound_to_type_parameter() async {
     await analyze('''
 class C<T extends List<int>> {
@@ -592,7 +612,11 @@
     await analyze(code);
     var targetEdge =
         assertEdge(decoratedTypeAnnotation('C y').node, never, hard: true);
-    expect((targetEdge.origin as CompoundAssignmentOrigin).offset,
+    expect(
+        (graph.getEdgeOrigin(targetEdge) as CompoundAssignmentOrigin)
+            .node
+            .operator
+            .offset,
         code.indexOf('+='));
     assertNullCheck(
         checkExpression('z);'),
@@ -603,7 +627,11 @@
         decoratedTypeAnnotation('C operator').node,
         decoratedTypeAnnotation('C y').node,
         hard: false);
-    expect((operatorReturnEdge.origin as CompoundAssignmentOrigin).offset,
+    expect(
+        (graph.getEdgeOrigin(operatorReturnEdge) as CompoundAssignmentOrigin)
+            .node
+            .operator
+            .offset,
         code.indexOf('+='));
     var fReturnEdge = assertEdge(decoratedTypeAnnotation('C operator').node,
         decoratedTypeAnnotation('C f').node,
@@ -621,7 +649,11 @@
     await analyze(code);
     var targetEdge =
         assertEdge(decoratedTypeAnnotation('C<int> y').node, never, hard: true);
-    expect((targetEdge.origin as CompoundAssignmentOrigin).offset,
+    expect(
+        (graph.getEdgeOrigin(targetEdge) as CompoundAssignmentOrigin)
+            .node
+            .operator
+            .offset,
         code.indexOf('+='));
     assertNullCheck(
         checkExpression('z);'),
@@ -632,7 +664,11 @@
         decoratedTypeAnnotation('C<T> operator').node,
         decoratedTypeAnnotation('C<int> y').node,
         hard: false);
-    expect((operatorReturnEdge.origin as CompoundAssignmentOrigin).offset,
+    expect(
+        (graph.getEdgeOrigin(operatorReturnEdge) as CompoundAssignmentOrigin)
+            .node
+            .operator
+            .offset,
         code.indexOf('+='));
     var fReturnEdge = assertEdge(decoratedTypeAnnotation('C<T> operator').node,
         decoratedTypeAnnotation('C<int> f').node,
@@ -1732,6 +1768,92 @@
         decoratedTypeAnnotation('int i').node);
   }
 
+  test_for_each_element_with_declaration() async {
+    await analyze('''
+void f(List<int> l) {
+  [for (int i in l) 0];
+}
+''');
+    assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
+    assertEdge(substitutionNode(decoratedTypeAnnotation('int> l').node, never),
+        decoratedTypeAnnotation('int i').node,
+        hard: false);
+  }
+
+  test_for_each_element_with_declaration_implicit_type() async {
+    await analyze('''
+void f(List<int> l) {
+  [for (var i in l) g(i)];
+}
+int g(int j) => 0;
+''');
+    var jNode = decoratedTypeAnnotation('int j').node;
+    var iMatcher = anyNode;
+    assertEdge(iMatcher, jNode, hard: false);
+    var iNode = iMatcher.matchingNode;
+    assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
+    assertEdge(
+        substitutionNode(decoratedTypeAnnotation('int> l').node, never), iNode,
+        hard: false);
+  }
+
+  test_for_each_element_with_identifier() async {
+    await analyze('''
+void f(List<int> l) {
+  int x;
+  [for (x in l) 0];
+}
+''');
+    assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
+    assertEdge(substitutionNode(decoratedTypeAnnotation('int> l').node, never),
+        decoratedTypeAnnotation('int x').node,
+        hard: false);
+  }
+
+  test_for_each_with_declaration() async {
+    await analyze('''
+void f(List<int> l) {
+  for (int i in l) {}
+}
+''');
+    assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
+    assertEdge(substitutionNode(decoratedTypeAnnotation('int> l').node, never),
+        decoratedTypeAnnotation('int i').node,
+        hard: false);
+  }
+
+  test_for_each_with_declaration_implicit_type() async {
+    await analyze('''
+void f(List<int> l) {
+  for (var i in l) {
+    g(i);
+  }
+}
+void g(int j) {}
+''');
+    var jNode = decoratedTypeAnnotation('int j').node;
+    var iMatcher = anyNode;
+    assertEdge(iMatcher, jNode, hard: false);
+    var iNode = iMatcher.matchingNode;
+    assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
+    assertEdge(
+        substitutionNode(decoratedTypeAnnotation('int> l').node, never), iNode,
+        hard: false);
+  }
+
+  test_for_each_with_identifier() async {
+    await analyze('''
+void f(List<int> l) {
+  int x;
+  for (x in l) {}
+}
+''');
+    assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
+    assertEdge(substitutionNode(decoratedTypeAnnotation('int> l').node, never),
+        decoratedTypeAnnotation('int x').node,
+        hard: false);
+  }
+
   test_for_element_list() async {
     await analyze('''
 void f(List<int> ints) {
@@ -2463,7 +2585,7 @@
 ''');
     var edge = assertEdge(anyNode, decoratedTypeAnnotation('int> f').node,
         hard: false);
-    var inferredTypeArgument = edge.primarySource;
+    var inferredTypeArgument = edge.sourceNode;
     assertEdge(
         decoratedTypeAnnotation('int> x').node,
         substitutionNode(
@@ -2482,8 +2604,8 @@
     var nullable_c_t = decoratedTypeAnnotation('C<int>').typeArguments[0].node;
     var nullable_t = decoratedTypeAnnotation('T t').node;
     var check_i = checkExpression('i/*check*/');
-    var nullable_c_t_or_nullable_t =
-        check_i.edges.single.destinationNode as NullabilityNodeForSubstitution;
+    var nullable_c_t_or_nullable_t = check_i.checks.edges.single.destinationNode
+        as NullabilityNodeForSubstitution;
     expect(nullable_c_t_or_nullable_t.innerNode, same(nullable_c_t));
     expect(nullable_c_t_or_nullable_t.outerNode, same(nullable_t));
     assertNullCheck(check_i,
@@ -2501,8 +2623,8 @@
     var nullable_c_t = decoratedTypeAnnotation('C<int>').typeArguments[0].node;
     var nullable_t = decoratedTypeAnnotation('T t').node;
     var check_i = checkExpression('i/*check*/');
-    var nullable_c_t_or_nullable_t =
-        check_i.edges.single.destinationNode as NullabilityNodeForSubstitution;
+    var nullable_c_t_or_nullable_t = check_i.checks.edges.single.destinationNode
+        as NullabilityNodeForSubstitution;
     expect(nullable_c_t_or_nullable_t.innerNode, same(nullable_c_t));
     expect(nullable_c_t_or_nullable_t.outerNode, same(nullable_t));
     assertNullCheck(check_i,
@@ -2650,6 +2772,18 @@
   }
 
   @failingTest
+  test_isExpression_directlyRelatedTypeParameter() async {
+    await analyze('''
+bool f(List<num> list) => list is List<int>
+''');
+    assertNoUpstreamNullability(decoratedTypeAnnotation('bool').node);
+    assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: false);
+    assertEdge(decoratedTypeAnnotation('num').node,
+        decoratedTypeAnnotation('int').node,
+        hard: false);
+  }
+
+  @failingTest
   test_isExpression_genericFunctionType() async {
     await analyze('''
 bool f(a) => a is int Function(String);
@@ -2657,19 +2791,33 @@
     assertNoUpstreamNullability(decoratedTypeAnnotation('bool').node);
   }
 
+  @failingTest
+  test_isExpression_indirectlyRelatedTypeParameter() async {
+    await analyze('''
+bool f(Iterable<num> iter) => iter is List<int>
+''');
+    assertNoUpstreamNullability(decoratedTypeAnnotation('bool').node);
+    assertEdge(decoratedTypeAnnotation('List').node, never, hard: false);
+    assertEdge(decoratedTypeAnnotation('num').node,
+        decoratedTypeAnnotation('int').node,
+        hard: false);
+  }
+
   test_isExpression_typeName_noTypeArguments() async {
     await analyze('''
 bool f(a) => a is String;
 ''');
     assertNoUpstreamNullability(decoratedTypeAnnotation('bool').node);
+    assertEdge(decoratedTypeAnnotation('String').node, never, hard: false);
   }
 
-  @failingTest
   test_isExpression_typeName_typeArguments() async {
     await analyze('''
 bool f(a) => a is List<int>;
 ''');
     assertNoUpstreamNullability(decoratedTypeAnnotation('bool').node);
+    assertEdge(decoratedTypeAnnotation('List').node, never, hard: false);
+    assertEdge(always, decoratedTypeAnnotation('int').node, hard: false);
   }
 
   test_library_metadata() async {
@@ -2701,7 +2849,7 @@
     expect(returnTypeEdges.length, 1);
     final returnTypeEdge = returnTypeEdges.single;
 
-    final listArgType = returnTypeEdge.primarySource;
+    final listArgType = returnTypeEdge.sourceNode;
     assertNoUpstreamNullability(listArgType);
   }
 
@@ -2718,7 +2866,7 @@
     expect(returnTypeEdges.length, 1);
     final returnTypeEdge = returnTypeEdges.single;
 
-    final listArgType = returnTypeEdge.primarySource;
+    final listArgType = returnTypeEdge.sourceNode;
     assertEdge(always, listArgType, hard: false);
   }
 
@@ -2919,8 +3067,8 @@
     var nullable_c_t = decoratedTypeAnnotation('C<int>').typeArguments[0].node;
     var nullable_t = decoratedTypeAnnotation('T t').node;
     var check_i = checkExpression('i/*check*/');
-    var nullable_c_t_or_nullable_t =
-        check_i.edges.single.destinationNode as NullabilityNodeForSubstitution;
+    var nullable_c_t_or_nullable_t = check_i.checks.edges.single.destinationNode
+        as NullabilityNodeForSubstitution;
     expect(nullable_c_t_or_nullable_t.innerNode, same(nullable_c_t));
     expect(nullable_c_t_or_nullable_t.outerNode, same(nullable_t));
     assertNullCheck(check_i,
@@ -2945,8 +3093,8 @@
         .node;
     expect(nullable_t, same(never));
     var check_i = checkExpression('i/*check*/');
-    var nullable_list_t_or_nullable_t =
-        check_i.edges.single.destinationNode as NullabilityNodeForSubstitution;
+    var nullable_list_t_or_nullable_t = check_i
+        .checks.edges.single.destinationNode as NullabilityNodeForSubstitution;
     expect(nullable_list_t_or_nullable_t.innerNode, same(nullable_list_t));
     expect(nullable_list_t_or_nullable_t.outerNode, same(nullable_t));
     assertNullCheck(check_i,
@@ -2964,8 +3112,8 @@
     var nullable_f_t = decoratedTypeAnnotation('int>').node;
     var nullable_t = decoratedTypeAnnotation('T t').node;
     var check_i = checkExpression('i/*check*/');
-    var nullable_f_t_or_nullable_t =
-        check_i.edges.single.destinationNode as NullabilityNodeForSubstitution;
+    var nullable_f_t_or_nullable_t = check_i.checks.edges.single.destinationNode
+        as NullabilityNodeForSubstitution;
     expect(nullable_f_t_or_nullable_t.innerNode, same(nullable_f_t));
     expect(nullable_f_t_or_nullable_t.outerNode, same(nullable_t));
     assertNullCheck(check_i,
@@ -3057,8 +3205,8 @@
 ''');
     var check_i = checkExpression('(f<int>(1))');
     var nullable_f_t = decoratedTypeAnnotation('int>').node;
-    var nullable_f_t_or_nullable_t =
-        check_i.edges.single.primarySource as NullabilityNodeForSubstitution;
+    var nullable_f_t_or_nullable_t = check_i.checks.edges.single.sourceNode
+        as NullabilityNodeForSubstitution;
     var nullable_t = decoratedTypeAnnotation('T f').node;
     expect(nullable_f_t_or_nullable_t.innerNode, same(nullable_f_t));
     expect(nullable_f_t_or_nullable_t.outerNode, same(nullable_t));
@@ -4446,9 +4594,9 @@
 
     assertNoUpstreamNullability(mapNode);
     assertNoUpstreamNullability(
-        assertEdge(anyNode, keyNode, hard: false).primarySource);
+        assertEdge(anyNode, keyNode, hard: false).sourceNode);
     assertNoUpstreamNullability(
-        assertEdge(anyNode, valueNode, hard: false).primarySource);
+        assertEdge(anyNode, valueNode, hard: false).sourceNode);
   }
 
   test_setOrMapLiteral_map_noTypeArgument_nullableKey() async {
@@ -4462,10 +4610,10 @@
     var mapNode = decoratedTypeAnnotation('Map').node;
 
     assertNoUpstreamNullability(mapNode);
-    assertEdge(always, assertEdge(anyNode, keyNode, hard: false).primarySource,
+    assertEdge(always, assertEdge(anyNode, keyNode, hard: false).sourceNode,
         hard: false);
     assertNoUpstreamNullability(
-        assertEdge(anyNode, valueNode, hard: false).primarySource);
+        assertEdge(anyNode, valueNode, hard: false).sourceNode);
   }
 
   test_setOrMapLiteral_map_noTypeArgument_nullableKeyAndValue() async {
@@ -4479,10 +4627,9 @@
     var mapNode = decoratedTypeAnnotation('Map').node;
 
     assertNoUpstreamNullability(mapNode);
-    assertEdge(always, assertEdge(anyNode, keyNode, hard: false).primarySource,
+    assertEdge(always, assertEdge(anyNode, keyNode, hard: false).sourceNode,
         hard: false);
-    assertEdge(
-        always, assertEdge(anyNode, valueNode, hard: false).primarySource,
+    assertEdge(always, assertEdge(anyNode, valueNode, hard: false).sourceNode,
         hard: false);
   }
 
@@ -4498,9 +4645,8 @@
 
     assertNoUpstreamNullability(mapNode);
     assertNoUpstreamNullability(
-        assertEdge(anyNode, keyNode, hard: false).primarySource);
-    assertEdge(
-        always, assertEdge(anyNode, valueNode, hard: false).primarySource,
+        assertEdge(anyNode, keyNode, hard: false).sourceNode);
+    assertEdge(always, assertEdge(anyNode, valueNode, hard: false).sourceNode,
         hard: false);
   }
 
@@ -4569,7 +4715,7 @@
 
     assertNoUpstreamNullability(setNode);
     assertNoUpstreamNullability(
-        assertEdge(anyNode, valueNode, hard: false).primarySource);
+        assertEdge(anyNode, valueNode, hard: false).sourceNode);
   }
 
   test_setOrMapLiteral_set_noTypeArgument_nullableElement() async {
@@ -4582,8 +4728,7 @@
     var setNode = decoratedTypeAnnotation('Set').node;
 
     assertNoUpstreamNullability(setNode);
-    assertEdge(
-        always, assertEdge(anyNode, valueNode, hard: false).primarySource,
+    assertEdge(always, assertEdge(anyNode, valueNode, hard: false).sourceNode,
         hard: false);
   }
 
@@ -4952,7 +5097,7 @@
     await analyze('''
 void f(List<int> x) {}
 ''');
-    var listClass = typeProvider.listType.element;
+    var listClass = typeProvider.listElement;
     var listBound =
         variables.decoratedTypeParameterBound(listClass.typeParameters[0]);
     expect(listBound.type.toString(), 'dynamic');
@@ -5062,7 +5207,13 @@
     var class_ = (type.type as InterfaceType).element;
     if (class_ == superclass) return type;
     if (superclass.name == 'Object') {
-      return DecoratedType(superclass.type, type.node);
+      return DecoratedType(
+        superclass.instantiate(
+          typeArguments: const [],
+          nullabilitySuffix: NullabilitySuffix.star,
+        ),
+        type.node,
+      );
     }
     if (class_.name == 'MyListOfList' && superclass.name == 'List') {
       return assignmentCheckerTest._myListOfListSupertype
@@ -5070,8 +5221,13 @@
     }
     if (class_.name == 'Future' && superclass.name == 'FutureOr') {
       return DecoratedType(
-          superclass.type.instantiate([type.typeArguments[0].type]), type.node,
-          typeArguments: [type.typeArguments[0]]);
+        superclass.instantiate(
+          typeArguments: [type.typeArguments[0].type],
+          nullabilitySuffix: NullabilitySuffix.star,
+        ),
+        type.node,
+        typeArguments: [type.typeArguments[0]],
+      );
     }
     throw UnimplementedError(
         'TODO(paulberry): asInstanceOf($type, $superclass)');
@@ -5084,6 +5240,8 @@
   }
 }
 
-class _TestEdgeOrigin extends EdgeOrigin {
+class _TestEdgeOrigin implements EdgeOrigin {
   const _TestEdgeOrigin();
+
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
diff --git a/pkg/nnbd_migration/test/instrumentation_test.dart b/pkg/nnbd_migration/test/instrumentation_test.dart
new file mode 100644
index 0000000..942bb85
--- /dev/null
+++ b/pkg/nnbd_migration/test/instrumentation_test.dart
@@ -0,0 +1,849 @@
+// 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/element/element.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/test_utilities/find_node.dart';
+import 'package:nnbd_migration/instrumentation.dart';
+import 'package:nnbd_migration/nnbd_migration.dart';
+import 'package:nnbd_migration/nullability_state.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'abstract_context.dart';
+import 'api_test_base.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(_InstrumentationTest);
+  });
+}
+
+class _InstrumentationClient implements NullabilityMigrationInstrumentation {
+  final _InstrumentationTest test;
+
+  _InstrumentationClient(this.test);
+
+  @override
+  void explicitTypeNullability(
+      Source source, TypeAnnotation typeAnnotation, NullabilityNodeInfo node) {
+    expect(source, test.source);
+    expect(test.explicitTypeNullability, isNot(contains(typeAnnotation)));
+    test.explicitTypeNullability[typeAnnotation] = node;
+  }
+
+  @override
+  void externalDecoratedType(Element element, DecoratedTypeInfo decoratedType) {
+    expect(test.externalDecoratedType, isNot(contains(element)));
+    test.externalDecoratedType[element] = decoratedType;
+  }
+
+  @override
+  void fix(SingleNullabilityFix fix, Iterable<FixReasonInfo> reasons) {
+    test.fixes[fix] = reasons.toList();
+  }
+
+  @override
+  void graphEdge(EdgeInfo edge, EdgeOriginInfo originInfo) {
+    expect(test.edgeOrigin, isNot(contains(edge)));
+    test.edges.add(edge);
+    test.edgeOrigin[edge] = originInfo;
+  }
+
+  @override
+  void immutableNodes(NullabilityNodeInfo never, NullabilityNodeInfo always) {
+    test.never = never;
+    test.always = always;
+  }
+
+  @override
+  void implicitReturnType(
+      Source source, AstNode node, DecoratedTypeInfo decoratedReturnType) {
+    expect(source, test.source);
+    expect(test.implicitReturnType, isNot(contains(node)));
+    test.implicitReturnType[node] = decoratedReturnType;
+  }
+
+  @override
+  void implicitType(
+      Source source, AstNode node, DecoratedTypeInfo decoratedType) {
+    expect(source, test.source);
+    expect(test.implicitType, isNot(contains(node)));
+    test.implicitType[node] = decoratedType;
+  }
+
+  @override
+  void implicitTypeArguments(
+      Source source, AstNode node, Iterable<DecoratedTypeInfo> types) {
+    expect(source, test.source);
+    expect(test.implicitTypeArguments, isNot(contains(node)));
+    test.implicitTypeArguments[node] = types.toList();
+  }
+
+  @override
+  void propagationStep(PropagationInfo info) {
+    test.propagationSteps.add(info);
+  }
+}
+
+@reflectiveTest
+class _InstrumentationTest extends AbstractContextTest {
+  NullabilityNodeInfo always;
+
+  final Map<TypeAnnotation, NullabilityNodeInfo> explicitTypeNullability = {};
+
+  final Map<Element, DecoratedTypeInfo> externalDecoratedType = {};
+
+  final List<EdgeInfo> edges = [];
+
+  Map<SingleNullabilityFix, List<FixReasonInfo>> fixes = {};
+
+  final Map<AstNode, DecoratedTypeInfo> implicitReturnType = {};
+
+  final Map<AstNode, DecoratedTypeInfo> implicitType = {};
+
+  final Map<AstNode, List<DecoratedTypeInfo>> implicitTypeArguments = {};
+
+  NullabilityNodeInfo never;
+
+  final List<PropagationInfo> propagationSteps = [];
+
+  final Map<EdgeInfo, EdgeOriginInfo> edgeOrigin = {};
+
+  FindNode findNode;
+
+  Source source;
+
+  Future<void> analyze(String content) async {
+    var sourcePath = convertPath('/home/test/lib/test.dart');
+    newFile(sourcePath, content: content);
+    var listener = new TestMigrationListener();
+    var migration = NullabilityMigration(listener,
+        instrumentation: _InstrumentationClient(this));
+    var result = await session.getResolvedUnit(sourcePath);
+    source = result.unit.declaredElement.source;
+    findNode = FindNode(content, result.unit);
+    migration.prepareInput(result);
+    migration.processInput(result);
+    migration.finish();
+  }
+
+  test_explicitTypeNullability() async {
+    var content = '''
+int x = 1;
+int y = null;
+''';
+    await analyze(content);
+    expect(explicitTypeNullability[findNode.typeAnnotation('int x')].isNullable,
+        false);
+    expect(explicitTypeNullability[findNode.typeAnnotation('int y')].isNullable,
+        true);
+  }
+
+  test_externalDecoratedType() async {
+    await analyze('''
+main() {
+  print(1);
+}
+''');
+    expect(
+        externalDecoratedType[findNode.simple('print').staticElement]
+            .type
+            .toString(),
+        'void Function(Object)');
+  }
+
+  test_fix_reason_edge() async {
+    await analyze('''
+void f(int x) {
+  print(x.isEven);
+}
+void g(int y, bool b) {
+  if (b) {
+    f(y);
+  }
+}
+main() {
+  g(null, false);
+}
+''');
+    var yUsage = findNode.simple('y);');
+    var entry =
+        fixes.entries.where((e) => e.key.location.offset == yUsage.end).single;
+    var reasons = entry.value;
+    expect(reasons, hasLength(1));
+    var edge = reasons[0] as EdgeInfo;
+    expect(edge.sourceNode,
+        same(explicitTypeNullability[findNode.typeAnnotation('int y')]));
+    expect(edge.destinationNode,
+        same(explicitTypeNullability[findNode.typeAnnotation('int x')]));
+    expect(edge.isSatisfied, false);
+    expect(edgeOrigin[edge].node, same(yUsage));
+  }
+
+  test_fix_reason_node() async {
+    await analyze('''
+int x = null;
+''');
+    var entries = fixes.entries.toList();
+    expect(entries, hasLength(1));
+    var intAnnotation = findNode.typeAnnotation('int');
+    expect(entries.single.key.location.offset, intAnnotation.end);
+    var reasons = entries.single.value;
+    expect(reasons, hasLength(1));
+    expect(reasons.single, same(explicitTypeNullability[intAnnotation]));
+  }
+
+  test_graphEdge() async {
+    await analyze('''
+int f(int x) => x;
+''');
+    var xNode = explicitTypeNullability[findNode.typeAnnotation('int x')];
+    var returnNode = explicitTypeNullability[findNode.typeAnnotation('int f')];
+    expect(
+        edges.where(
+            (e) => e.sourceNode == xNode && e.destinationNode == returnNode),
+        hasLength(1));
+  }
+
+  test_graphEdge_guards() async {
+    await analyze('''
+int f(int i, int j) {
+  if (i == null) {
+    return j;
+  }
+  return 1;
+}
+''');
+    var iNode = explicitTypeNullability[findNode.typeAnnotation('int i')];
+    var jNode = explicitTypeNullability[findNode.typeAnnotation('int j')];
+    var returnNode = explicitTypeNullability[findNode.typeAnnotation('int f')];
+    var matchingEdges = edges
+        .where((e) => e.sourceNode == jNode && e.destinationNode == returnNode)
+        .toList();
+    expect(matchingEdges, hasLength(1));
+    expect(matchingEdges.single.guards, hasLength(1));
+    expect(matchingEdges.single.guards.single, iNode);
+  }
+
+  test_graphEdge_hard() async {
+    await analyze('''
+int f(int x) => x;
+''');
+    var xNode = explicitTypeNullability[findNode.typeAnnotation('int x')];
+    var returnNode = explicitTypeNullability[findNode.typeAnnotation('int f')];
+    var matchingEdges = edges
+        .where((e) => e.sourceNode == xNode && e.destinationNode == returnNode)
+        .toList();
+    expect(matchingEdges, hasLength(1));
+    expect(matchingEdges.single.isUnion, false);
+    expect(matchingEdges.single.isHard, true);
+  }
+
+  test_graphEdge_isSatisfied() async {
+    await analyze('''
+void f1(int i, bool b) {
+  f2(i, b);
+}
+void f2(int j, bool b) {
+  if (b) {
+    f3(j);
+  }
+}
+void f3(int k) {
+  f4(k);
+}
+void f4(int l) {
+  print(l.isEven);
+}
+main() {
+  f1(null, false);
+}
+''');
+    var iNode = explicitTypeNullability[findNode.typeAnnotation('int i')];
+    var jNode = explicitTypeNullability[findNode.typeAnnotation('int j')];
+    var kNode = explicitTypeNullability[findNode.typeAnnotation('int k')];
+    var lNode = explicitTypeNullability[findNode.typeAnnotation('int l')];
+    var iToJ = edges
+        .where((e) => e.sourceNode == iNode && e.destinationNode == jNode)
+        .single;
+    var jToK = edges
+        .where((e) => e.sourceNode == jNode && e.destinationNode == kNode)
+        .single;
+    var kToL = edges
+        .where((e) => e.sourceNode == kNode && e.destinationNode == lNode)
+        .single;
+    expect(iNode.isNullable, true);
+    expect(jNode.isNullable, true);
+    expect(kNode.isNullable, false);
+    expect(lNode.isNullable, false);
+    expect(iToJ.isSatisfied, true);
+    expect(jToK.isSatisfied, false);
+    expect(kToL.isSatisfied, true);
+  }
+
+  test_graphEdge_origin() async {
+    await analyze('''
+int f(int x) => x;
+''');
+    var xNode = explicitTypeNullability[findNode.typeAnnotation('int x')];
+    var returnNode = explicitTypeNullability[findNode.typeAnnotation('int f')];
+    var matchingEdges = edges
+        .where((e) => e.sourceNode == xNode && e.destinationNode == returnNode)
+        .toList();
+    var origin = edgeOrigin[matchingEdges.single];
+    expect(origin.source, source);
+    expect(origin.node, findNode.simple('x;'));
+  }
+
+  test_graphEdge_soft() async {
+    await analyze('''
+int f(int x, bool b) {
+  if (b) return x;
+  return 0;
+}
+''');
+    var xNode = explicitTypeNullability[findNode.typeAnnotation('int x')];
+    var returnNode = explicitTypeNullability[findNode.typeAnnotation('int f')];
+    var matchingEdges = edges
+        .where((e) => e.sourceNode == xNode && e.destinationNode == returnNode)
+        .toList();
+    expect(matchingEdges, hasLength(1));
+    expect(matchingEdges.single.isUnion, false);
+    expect(matchingEdges.single.isHard, false);
+  }
+
+  test_graphEdge_union() async {
+    await analyze('''
+class C {
+  int i;
+  C(this.i); /*constructor*/
+}
+''');
+    var fieldNode = explicitTypeNullability[findNode.typeAnnotation('int')];
+    var formalParamNode =
+        implicitType[findNode.fieldFormalParameter('i); /*constructor*/')].node;
+    var matchingEdges = edges
+        .where((e) =>
+            e.sourceNode == fieldNode && e.destinationNode == formalParamNode)
+        .toList();
+    expect(matchingEdges, hasLength(1));
+    expect(matchingEdges.single.isUnion, true);
+    expect(matchingEdges.single.isHard, true);
+    matchingEdges = edges
+        .where((e) =>
+            e.sourceNode == formalParamNode && e.destinationNode == fieldNode)
+        .toList();
+    expect(matchingEdges, hasLength(1));
+    expect(matchingEdges.single.isUnion, true);
+    expect(matchingEdges.single.isHard, true);
+  }
+
+  test_immutableNode_always() async {
+    await analyze('''
+int x = null;
+''');
+    expect(always.isImmutable, true);
+    expect(always.isNullable, true);
+    var xNode = explicitTypeNullability[findNode.typeAnnotation('int')];
+    var edge = edges.where((e) => e.destinationNode == xNode).single;
+    expect(edge.sourceNode, always);
+  }
+
+  test_immutableNode_never() async {
+    await analyze('''
+bool f(int x) => x.isEven;
+''');
+    expect(never.isImmutable, true);
+    expect(never.isNullable, false);
+    var xNode = explicitTypeNullability[findNode.typeAnnotation('int')];
+    var edge = edges.where((e) => e.sourceNode == xNode).single;
+    expect(edge.destinationNode, never);
+  }
+
+  test_implicitReturnType_constructor() async {
+    await analyze('''
+class C {
+  factory C() => f(true);
+  C.named();
+}
+C f(bool b) => b ? C.named() : null;
+''');
+    var factoryReturnNode = implicitReturnType[findNode.constructor('C(')].node;
+    var fReturnNode = explicitTypeNullability[findNode.typeAnnotation('C f')];
+    expect(
+        edges.where((e) =>
+            e.sourceNode == fReturnNode &&
+            e.destinationNode == factoryReturnNode),
+        hasLength(1));
+  }
+
+  test_implicitReturnType_formalParameter() async {
+    await analyze('''
+Object f(callback()) => callback();
+''');
+    var paramReturnNode =
+        implicitReturnType[findNode.functionTypedFormalParameter('callback())')]
+            .node;
+    var fReturnNode =
+        explicitTypeNullability[findNode.typeAnnotation('Object')];
+    expect(
+        edges.where((e) =>
+            e.sourceNode == paramReturnNode &&
+            e.destinationNode == fReturnNode),
+        hasLength(1));
+  }
+
+  test_implicitReturnType_function() async {
+    await analyze('''
+f() => 1;
+Object g() => f();
+''');
+    var fReturnNode =
+        implicitReturnType[findNode.functionDeclaration('f() =>')].node;
+    var gReturnNode =
+        explicitTypeNullability[findNode.typeAnnotation('Object')];
+    expect(
+        edges.where((e) =>
+            e.sourceNode == fReturnNode && e.destinationNode == gReturnNode),
+        hasLength(1));
+  }
+
+  test_implicitReturnType_functionExpression() async {
+    await analyze('''
+main() {
+  int Function() f = () => g();
+}
+int g() => 1;
+''');
+    var fReturnNode =
+        explicitTypeNullability[findNode.typeAnnotation('int Function')];
+    var functionExpressionReturnNode =
+        implicitReturnType[findNode.functionExpression('() => g()')].node;
+    var gReturnNode = explicitTypeNullability[findNode.typeAnnotation('int g')];
+    expect(
+        edges.where((e) =>
+            e.sourceNode == gReturnNode &&
+            e.destinationNode == functionExpressionReturnNode),
+        hasLength(1));
+    expect(
+        edges.where((e) =>
+            e.sourceNode == functionExpressionReturnNode &&
+            e.destinationNode == fReturnNode),
+        hasLength(1));
+  }
+
+  test_implicitReturnType_functionTypeAlias() async {
+    await analyze('''
+typedef F();
+Object f(F callback) => callback();
+''');
+    var typedefReturnNode =
+        implicitReturnType[findNode.functionTypeAlias('F()')].node;
+    var fReturnNode =
+        explicitTypeNullability[findNode.typeAnnotation('Object')];
+    expect(
+        edges.where((e) =>
+            e.sourceNode == typedefReturnNode &&
+            e.destinationNode == fReturnNode),
+        hasLength(1));
+  }
+
+  test_implicitReturnType_genericFunctionType() async {
+    await analyze('''
+Object f(Function() callback) => callback();
+''');
+    var callbackReturnNode =
+        implicitReturnType[findNode.genericFunctionType('Function()')].node;
+    var fReturnNode =
+        explicitTypeNullability[findNode.typeAnnotation('Object')];
+    expect(
+        edges.where((e) =>
+            e.sourceNode == callbackReturnNode &&
+            e.destinationNode == fReturnNode),
+        hasLength(1));
+  }
+
+  test_implicitReturnType_method() async {
+    await analyze('''
+abstract class Base {
+  int f();
+}
+abstract class Derived extends Base {
+  f /*derived*/();
+}
+''');
+    var baseReturnNode =
+        explicitTypeNullability[findNode.typeAnnotation('int')];
+    var derivedReturnNode =
+        implicitReturnType[findNode.methodDeclaration('f /*derived*/')].node;
+    expect(
+        edges.where((e) =>
+            e.sourceNode == derivedReturnNode &&
+            e.destinationNode == baseReturnNode),
+        hasLength(1));
+  }
+
+  test_implicitType_catch_exception() async {
+    await analyze('''
+void f() {
+  try {} catch (e) {
+    Object o = e;
+  }
+}
+''');
+    var oNode = explicitTypeNullability[findNode.typeAnnotation('Object')];
+    var eNode = implicitType[findNode.simple('e)')].node;
+    expect(
+        edges.where((e) => e.sourceNode == eNode && e.destinationNode == oNode),
+        hasLength(1));
+  }
+
+  test_implicitType_catch_stackTrace() async {
+    await analyze('''
+void f() {
+  try {} catch (e, st) {
+    Object o = st;
+  }
+}
+''');
+    var oNode = explicitTypeNullability[findNode.typeAnnotation('Object')];
+    var stNode = implicitType[findNode.simple('st)')].node;
+    expect(
+        edges
+            .where((e) => e.sourceNode == stNode && e.destinationNode == oNode),
+        hasLength(1));
+  }
+
+  test_implicitType_declaredIdentifier_forEachPartsWithDeclaration() async {
+    await analyze('''
+void f(List<int> l) {
+  for (var x in l) {
+    int y = x;
+  }
+}
+''');
+    var xNode = implicitType[(findNode.forStatement('for').forLoopParts
+                as ForEachPartsWithDeclaration)
+            .loopVariable]
+        .node;
+    var yNode = explicitTypeNullability[findNode.typeAnnotation('int y')];
+    expect(
+        edges.where((e) => e.sourceNode == xNode && e.destinationNode == yNode),
+        hasLength(1));
+  }
+
+  test_implicitType_formalParameter() async {
+    await analyze('''
+abstract class Base {
+  void f(int i);
+}
+abstract class Derived extends Base {
+  void f(i); /*derived*/
+}
+''');
+    var baseParamNode =
+        explicitTypeNullability[findNode.typeAnnotation('int i')];
+    var derivedParamNode =
+        implicitType[findNode.simpleParameter('i); /*derived*/')].node;
+    expect(
+        edges.where((e) =>
+            e.sourceNode == baseParamNode &&
+            e.destinationNode == derivedParamNode),
+        hasLength(1));
+  }
+
+  test_implicitType_namedParameter() async {
+    await analyze('''
+abstract class Base {
+  void f(void callback({int i}));
+}
+abstract class Derived extends Base {
+  void f(callback);
+}
+''');
+    var baseParamParamNode =
+        explicitTypeNullability[findNode.typeAnnotation('int i')];
+    var derivedParamParamNode =
+        implicitType[findNode.simpleParameter('callback)')]
+            .namedParameter('i')
+            .node;
+    expect(
+        edges.where((e) =>
+            e.sourceNode == baseParamParamNode &&
+            e.destinationNode == derivedParamParamNode),
+        hasLength(1));
+  }
+
+  test_implicitType_positionalParameter() async {
+    await analyze('''
+abstract class Base {
+  void f(void callback(int i));
+}
+abstract class Derived extends Base {
+  void f(callback);
+}
+''');
+    var baseParamParamNode =
+        explicitTypeNullability[findNode.typeAnnotation('int i')];
+    var derivedParamParamNode =
+        implicitType[findNode.simpleParameter('callback)')]
+            .positionalParameter(0)
+            .node;
+    expect(
+        edges.where((e) =>
+            e.sourceNode == baseParamParamNode &&
+            e.destinationNode == derivedParamParamNode),
+        hasLength(1));
+  }
+
+  test_implicitType_returnType() async {
+    await analyze('''
+abstract class Base {
+  void f(int callback());
+}
+abstract class Derived extends Base {
+  void f(callback);
+}
+''');
+    var baseParamReturnNode =
+        explicitTypeNullability[findNode.typeAnnotation('int callback')];
+    var derivedParamReturnNode =
+        implicitType[findNode.simpleParameter('callback)')].returnType.node;
+    expect(
+        edges.where((e) =>
+            e.sourceNode == baseParamReturnNode &&
+            e.destinationNode == derivedParamReturnNode),
+        hasLength(1));
+  }
+
+  test_implicitType_typeArgument() async {
+    await analyze('''
+abstract class Base {
+  void f(List<int> x);
+}
+abstract class Derived extends Base {
+  void f(x); /*derived*/
+}
+''');
+    var baseParamArgNode =
+        explicitTypeNullability[findNode.typeAnnotation('int>')];
+    var derivedParamArgNode =
+        implicitType[findNode.simpleParameter('x); /*derived*/')]
+            .typeArgument(0)
+            .node;
+    expect(
+        edges.where((e) =>
+            e.sourceNode == derivedParamArgNode &&
+            e.destinationNode == baseParamArgNode),
+        hasLength(1));
+  }
+
+  test_implicitType_variableDeclarationList() async {
+    await analyze('''
+void f(int i) {
+  var j = i;
+}
+''');
+    var iNode = explicitTypeNullability[findNode.typeAnnotation('int')];
+    var jNode = implicitType[findNode.variableDeclarationList('j')].node;
+    expect(
+        edges.where((e) => e.sourceNode == iNode && e.destinationNode == jNode),
+        hasLength(1));
+  }
+
+  test_implicitTypeArguments_genericFunctionCall() async {
+    await analyze('''
+List<T> g<T>(T t) {}
+List<int> f() => g(null);
+''');
+    var implicitInvocationTypeArgumentNode =
+        implicitTypeArguments[findNode.methodInvocation('g(null)')].single.node;
+    var returnElementNode =
+        explicitTypeNullability[findNode.typeAnnotation('int')];
+    expect(edges.where((e) {
+      var destination = e.destinationNode;
+      return e.sourceNode == always &&
+          destination is SubstitutionNodeInfo &&
+          destination.innerNode == implicitInvocationTypeArgumentNode;
+    }), hasLength(1));
+    expect(edges.where((e) {
+      var source = e.sourceNode;
+      return source is SubstitutionNodeInfo &&
+          source.innerNode == implicitInvocationTypeArgumentNode &&
+          e.destinationNode == returnElementNode;
+    }), hasLength(1));
+  }
+
+  test_implicitTypeArguments_genericMethodCall() async {
+    await analyze('''
+class C {
+  List<T> g<T>(T t) {}
+}
+List<int> f(C c) => c.g(null);
+''');
+    var implicitInvocationTypeArgumentNode =
+        implicitTypeArguments[findNode.methodInvocation('c.g(null)')]
+            .single
+            .node;
+    var returnElementNode =
+        explicitTypeNullability[findNode.typeAnnotation('int')];
+    expect(edges.where((e) {
+      var destination = e.destinationNode;
+      return e.sourceNode == always &&
+          destination is SubstitutionNodeInfo &&
+          destination.innerNode == implicitInvocationTypeArgumentNode;
+    }), hasLength(1));
+    expect(edges.where((e) {
+      var source = e.sourceNode;
+      return source is SubstitutionNodeInfo &&
+          source.innerNode == implicitInvocationTypeArgumentNode &&
+          e.destinationNode == returnElementNode;
+    }), hasLength(1));
+  }
+
+  test_implicitTypeArguments_instanceCreationExpression() async {
+    await analyze('''
+class C<T> {
+  C(T t);
+}
+C<int> f() => C(null);
+''');
+    var implicitInvocationTypeArgumentNode =
+        implicitTypeArguments[findNode.instanceCreation('C(null)')].single.node;
+    var returnElementNode =
+        explicitTypeNullability[findNode.typeAnnotation('int')];
+    expect(edges.where((e) {
+      var destination = e.destinationNode;
+      return e.sourceNode == always &&
+          destination is SubstitutionNodeInfo &&
+          destination.innerNode == implicitInvocationTypeArgumentNode;
+    }), hasLength(1));
+    expect(
+        edges.where((e) =>
+            e.sourceNode == implicitInvocationTypeArgumentNode &&
+            e.destinationNode == returnElementNode),
+        hasLength(1));
+  }
+
+  test_implicitTypeArguments_listLiteral() async {
+    await analyze('''
+List<int> f() => [null];
+''');
+    var implicitListLiteralElementNode =
+        implicitTypeArguments[findNode.listLiteral('[null]')].single.node;
+    var returnElementNode =
+        explicitTypeNullability[findNode.typeAnnotation('int')];
+    expect(
+        edges.where((e) =>
+            e.sourceNode == always &&
+            e.destinationNode == implicitListLiteralElementNode),
+        hasLength(1));
+    expect(
+        edges.where((e) =>
+            e.sourceNode == implicitListLiteralElementNode &&
+            e.destinationNode == returnElementNode),
+        hasLength(1));
+  }
+
+  test_implicitTypeArguments_mapLiteral() async {
+    await analyze('''
+Map<int, String> f() => {1: null};
+''');
+    var implicitMapLiteralTypeArguments =
+        implicitTypeArguments[findNode.setOrMapLiteral('{1: null}')];
+    expect(implicitMapLiteralTypeArguments, hasLength(2));
+    var implicitMapLiteralKeyNode = implicitMapLiteralTypeArguments[0].node;
+    var implicitMapLiteralValueNode = implicitMapLiteralTypeArguments[1].node;
+    var returnKeyNode = explicitTypeNullability[findNode.typeAnnotation('int')];
+    var returnValueNode =
+        explicitTypeNullability[findNode.typeAnnotation('String')];
+    expect(
+        edges.where((e) =>
+            e.sourceNode == never &&
+            e.destinationNode == implicitMapLiteralKeyNode),
+        hasLength(1));
+    expect(
+        edges.where((e) =>
+            e.sourceNode == implicitMapLiteralKeyNode &&
+            e.destinationNode == returnKeyNode),
+        hasLength(1));
+    expect(
+        edges.where((e) =>
+            e.sourceNode == always &&
+            e.destinationNode == implicitMapLiteralValueNode),
+        hasLength(1));
+    expect(
+        edges.where((e) =>
+            e.sourceNode == implicitMapLiteralValueNode &&
+            e.destinationNode == returnValueNode),
+        hasLength(1));
+  }
+
+  test_implicitTypeArguments_setLiteral() async {
+    await analyze('''
+Set<int> f() => {null};
+''');
+    var implicitSetLiteralElementNode =
+        implicitTypeArguments[findNode.setOrMapLiteral('{null}')].single.node;
+    var returnElementNode =
+        explicitTypeNullability[findNode.typeAnnotation('int')];
+    expect(
+        edges.where((e) =>
+            e.sourceNode == always &&
+            e.destinationNode == implicitSetLiteralElementNode),
+        hasLength(1));
+    expect(
+        edges.where((e) =>
+            e.sourceNode == implicitSetLiteralElementNode &&
+            e.destinationNode == returnElementNode),
+        hasLength(1));
+  }
+
+  test_implicitTypeArguments_typeAnnotation() async {
+    await analyze('''
+List<Object> f(List l) => l;
+''');
+    var implicitListElementType =
+        implicitTypeArguments[findNode.typeAnnotation('List l')].single.node;
+    var implicitReturnElementType =
+        explicitTypeNullability[findNode.typeAnnotation('Object')];
+    expect(
+        edges.where((e) =>
+            e.sourceNode == implicitListElementType &&
+            e.destinationNode == implicitReturnElementType),
+        hasLength(1));
+  }
+
+  test_propagationStep() async {
+    await analyze('''
+int x = null;
+''');
+    var xNode = explicitTypeNullability[findNode.typeAnnotation('int')];
+    var step = propagationSteps.where((s) => s.node == xNode).single;
+    expect(step.newState, NullabilityState.ordinaryNullable);
+    expect(step.reason, StateChangeReason.downstream);
+    expect(step.edge.sourceNode, always);
+    expect(step.edge.destinationNode, xNode);
+  }
+
+  test_substitutionNode() async {
+    await analyze('''
+class C<T> {
+  void f(T t) {}
+}
+voig g(C<int> x, int y) {
+  x.f(y);
+}
+''');
+    var yNode = explicitTypeNullability[findNode.typeAnnotation('int y')];
+    var edge = edges.where((e) => e.sourceNode == yNode).single;
+    var sNode = edge.destinationNode as SubstitutionNodeInfo;
+    expect(sNode.innerNode,
+        explicitTypeNullability[findNode.typeAnnotation('int>')]);
+    expect(sNode.outerNode,
+        explicitTypeNullability[findNode.typeAnnotation('T t')]);
+  }
+}
diff --git a/pkg/nnbd_migration/test/migration_visitor_test_base.dart b/pkg/nnbd_migration/test/migration_visitor_test_base.dart
index f335eb45..4c16e02 100644
--- a/pkg/nnbd_migration/test/migration_visitor_test_base.dart
+++ b/pkg/nnbd_migration/test/migration_visitor_test_base.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -28,8 +29,12 @@
   NullabilityNode get matchingNode => _matchingNodes.single;
 
   @override
-  bool matches(NullabilityNode node) {
+  void matched(NullabilityNode node) {
     _matchingNodes.add(node);
+  }
+
+  @override
+  bool matches(NullabilityNode node) {
     return true;
   }
 }
@@ -80,15 +85,14 @@
   }
 
   DecoratedType future(DecoratedType parameter, {NullabilityNode node}) {
-    return DecoratedType(typeProvider.futureType.instantiate([parameter.type]),
-        node ?? newNode(),
+    return DecoratedType(
+        typeProvider.futureType2(parameter.type), node ?? newNode(),
         typeArguments: [parameter]);
   }
 
   DecoratedType futureOr(DecoratedType parameter, {NullabilityNode node}) {
     return DecoratedType(
-        typeProvider.futureOrType.instantiate([parameter.type]),
-        node ?? newNode(),
+        typeProvider.futureOrType2(parameter.type), node ?? newNode(),
         typeArguments: [parameter]);
   }
 
@@ -96,8 +100,7 @@
       DecoratedType(typeProvider.intType, node ?? newNode());
 
   DecoratedType list(DecoratedType elementType, {NullabilityNode node}) =>
-      DecoratedType(typeProvider.listType.instantiate([elementType.type]),
-          node ?? newNode(),
+      DecoratedType(typeProvider.listType2(elementType.type), node ?? newNode(),
           typeArguments: [elementType]);
 
   NullabilityNode newNode() => NullabilityNode.forTypeAnnotation(_offset++);
@@ -113,8 +116,14 @@
   }
 
   DecoratedType typeParameterType(TypeParameterElement typeParameter,
-          {NullabilityNode node}) =>
-      DecoratedType(typeParameter.type, node ?? newNode());
+      {NullabilityNode node}) {
+    return DecoratedType(
+      typeParameter.instantiate(
+        nullabilitySuffix: NullabilitySuffix.star,
+      ),
+      node ?? newNode(),
+    );
+  }
 }
 
 /// Base functionality that must be implemented by classes mixing in
@@ -159,7 +168,7 @@
       fail('Found multiple edges $source -> $destination');
     } else {
       var edge = edges[0];
-      expect(edge.hard, hard);
+      expect(edge.isHard, hard);
       expect(edge.guards, unorderedEquals(guards));
       return edge;
     }
@@ -187,7 +196,7 @@
     var edges = getEdges(x, y);
     for (var edge in edges) {
       if (edge.isUnion) {
-        expect(edge.sources, hasLength(1));
+        expect(edge.upstreamNodes, hasLength(1));
         return;
       }
     }
@@ -203,12 +212,16 @@
   List<NullabilityEdge> getEdges(Object source, Object destination) {
     var sourceMatcher = NodeMatcher(source);
     var destinationMatcher = NodeMatcher(destination);
-    return graph
-        .getAllEdges()
-        .where((e) =>
-            sourceMatcher.matches(e.primarySource) &&
-            destinationMatcher.matches(e.destinationNode))
-        .toList();
+    var result = <NullabilityEdge>[];
+    for (var edge in graph.getAllEdges()) {
+      if (sourceMatcher.matches(edge.sourceNode) &&
+          destinationMatcher.matches(edge.destinationNode)) {
+        sourceMatcher.matched(edge.sourceNode);
+        destinationMatcher.matched(edge.destinationNode);
+        result.add(edge);
+      }
+    }
+    return result;
   }
 
   /// Creates a [NodeMatcher] matching a substitution node whose inner and outer
@@ -227,7 +240,7 @@
 
   final _decoratedExpressionTypes = <Expression, DecoratedType>{};
 
-  final _expressionChecks = <Expression, ExpressionChecks>{};
+  final _expressionChecks = <Expression, ExpressionChecksOrigin>{};
 
   final _possiblyOptional = <DefaultFormalParameter, NullabilityNode>{};
 
@@ -235,7 +248,7 @@
       : super(graph, typeProvider);
 
   /// Gets the [ExpressionChecks] associated with the given [expression].
-  ExpressionChecks checkExpression(Expression expression) =>
+  ExpressionChecksOrigin checkExpression(Expression expression) =>
       _expressionChecks[_normalizeExpression(expression)];
 
   /// Gets the [conditionalDiscard] associated with the given [expression].
@@ -265,9 +278,9 @@
 
   @override
   void recordExpressionChecks(
-      Source source, Expression expression, ExpressionChecks checks) {
-    super.recordExpressionChecks(source, expression, checks);
-    _expressionChecks[_normalizeExpression(expression)] = checks;
+      Source source, Expression expression, ExpressionChecksOrigin origin) {
+    super.recordExpressionChecks(source, expression, origin);
+    _expressionChecks[_normalizeExpression(expression)] = origin;
   }
 
   @override
@@ -360,6 +373,8 @@
         'Unclear how to match node expectation of type ${expectation.runtimeType}');
   }
 
+  void matched(NullabilityNode node);
+
   bool matches(NullabilityNode node);
 }
 
@@ -370,6 +385,9 @@
   _ExactNodeMatcher(this._expectation);
 
   @override
+  void matched(NullabilityNode node) {}
+
+  @override
   bool matches(NullabilityNode node) => node == _expectation;
 }
 
@@ -382,6 +400,18 @@
   _SubstitutionNodeMatcher(this.inner, this.outer);
 
   @override
+  void matched(NullabilityNode node) {
+    if (node is NullabilityNodeForSubstitution) {
+      inner.matched(node.innerNode);
+      outer.matched(node.outerNode);
+    } else {
+      throw StateError(
+          'matched should only be called on nodes for which matches returned '
+          'true');
+    }
+  }
+
+  @override
   bool matches(NullabilityNode node) {
     return node is NullabilityNodeForSubstitution &&
         inner.matches(node.innerNode) &&
diff --git a/pkg/nnbd_migration/test/nullability_migration_impl_test.dart b/pkg/nnbd_migration/test/nullability_migration_impl_test.dart
index e145a95..39ba9f3 100644
--- a/pkg/nnbd_migration/test/nullability_migration_impl_test.dart
+++ b/pkg/nnbd_migration/test/nullability_migration_impl_test.dart
@@ -39,7 +39,7 @@
 
     when(innerModification.isEmpty).thenReturn(false);
 
-    NullabilityMigrationImpl.broadcast(variables, listener);
+    NullabilityMigrationImpl.broadcast(variables, listener, null);
 
     final fix = verify(listener.addFix(captureAny)).captured.single
         as SingleNullabilityFix;
@@ -68,7 +68,7 @@
 
     when(potentialModification.modifications).thenReturn([]);
 
-    NullabilityMigrationImpl.broadcast(variables, listener);
+    NullabilityMigrationImpl.broadcast(variables, listener, null);
 
     verifyNever(listener.addFix(any));
     verifyNever(listener.reportException(any, any, any, any));
@@ -80,7 +80,7 @@
     final source = SourceMock('');
     when(variables.getPotentialModifications()).thenReturn({source: []});
 
-    NullabilityMigrationImpl.broadcast(variables, listener);
+    NullabilityMigrationImpl.broadcast(variables, listener, null);
 
     verifyNever(listener.addFix(any));
     verifyNever(listener.reportException(any, any, any, any));
diff --git a/pkg/nnbd_migration/test/nullability_node_test.dart b/pkg/nnbd_migration/test/nullability_node_test.dart
index eac19ce..e256963e 100644
--- a/pkg/nnbd_migration/test/nullability_node_test.dart
+++ b/pkg/nnbd_migration/test/nullability_node_test.dart
@@ -628,4 +628,6 @@
   }
 }
 
-class _TestEdgeOrigin extends EdgeOrigin {}
+class _TestEdgeOrigin implements EdgeOrigin {
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
diff --git a/pkg/nnbd_migration/test/test_all.dart b/pkg/nnbd_migration/test/test_all.dart
index 48a36fd..fed8c12 100644
--- a/pkg/nnbd_migration/test/test_all.dart
+++ b/pkg/nnbd_migration/test/test_all.dart
@@ -12,7 +12,10 @@
 import 'edge_builder_flow_analysis_test.dart'
     as edge_builder_flow_analysis_test;
 import 'edge_builder_test.dart' as edge_builder_test;
+import 'instrumentation_test.dart' as instrumentation_test;
 import 'node_builder_test.dart' as node_builder_test;
+import 'nullability_migration_impl_test.dart'
+    as nullability_migration_impl_test;
 import 'nullability_node_test.dart' as nullability_node_test;
 import 'utilities/test_all.dart' as utilities;
 
@@ -24,7 +27,9 @@
     decorated_type_test.main();
     edge_builder_flow_analysis_test.main();
     edge_builder_test.main();
+    instrumentation_test.main();
     node_builder_test.main();
+    nullability_migration_impl_test.main();
     nullability_node_test.main();
     utilities.main();
   });
diff --git a/pkg/test_runner/lib/src/configuration.dart b/pkg/test_runner/lib/src/configuration.dart
index 47dfdae..ac08814 100644
--- a/pkg/test_runner/lib/src/configuration.dart
+++ b/pkg/test_runner/lib/src/configuration.dart
@@ -9,6 +9,7 @@
 import 'package:smith/smith.dart';
 
 import 'compiler_configuration.dart';
+import 'feature.dart';
 import 'path.dart';
 import 'repository.dart';
 import 'runtime_configuration.dart';
@@ -347,6 +348,33 @@
   CompilerConfiguration get compilerConfiguration =>
       _compilerConfiguration ??= CompilerConfiguration(this);
 
+  Set<Feature> _supportedFeatures;
+
+  /// The set of [Feature]s supported by this configuration.
+  Set<Feature> get supportedFeatures {
+    if (_supportedFeatures != null) return _supportedFeatures;
+
+    _supportedFeatures = {};
+    switch (nnbdMode) {
+      case NnbdMode.legacy:
+        _supportedFeatures.add(Feature.nnbdLegacy);
+        break;
+      case NnbdMode.weak:
+        _supportedFeatures.add(Feature.nnbd);
+        _supportedFeatures.add(Feature.nnbdWeak);
+        break;
+      case NnbdMode.strong:
+        _supportedFeatures.add(Feature.nnbd);
+        _supportedFeatures.add(Feature.nnbdStrong);
+        break;
+    }
+
+    // TODO(rnystrom): Define more features for things like "dart:io", separate
+    // int/double representation, etc.
+
+    return _supportedFeatures;
+  }
+
   /// Determines if this configuration has a compatible compiler and runtime
   /// and other valid fields.
   ///
diff --git a/pkg/test_runner/lib/src/feature.dart b/pkg/test_runner/lib/src/feature.dart
new file mode 100644
index 0000000..ae9d48b
--- /dev/null
+++ b/pkg/test_runner/lib/src/feature.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.
+
+/// A capability that a Dart implementation may or may not provide that a test
+/// may require.
+///
+/// Each [TestConfiguration] specifies the set of features it supports. A test
+/// can have a "// Requirements" comment indicating the names of features it
+/// requires. If a test requires a feature not supported by the current
+/// configution, the test runner automatically skips it.
+class Feature {
+  /// Opted out of NNBD and still using the legacy semantics.
+  static const nnbdLegacy = Feature._("nnbd-legacy");
+
+  /// Opted in to NNBD features.
+  ///
+  /// Note that this does not imply either strong or weak checking. A test that
+  /// only requires "nnbd" should run in both weak and strong checking modes.
+  static const nnbd = Feature._("nnbd");
+
+  /// Weak checking of NNBD features.
+  static const nnbdWeak = Feature._("nnbd-weak");
+
+  /// Full strong checking of NNBD features.
+  static const nnbdStrong = Feature._("nnbd-strong");
+
+  static const all = [nnbdLegacy, nnbd, nnbdWeak, nnbdStrong];
+
+  final String name;
+
+  const Feature._(this.name);
+
+  String toString() => name;
+}
diff --git a/pkg/test_runner/lib/src/multitest.dart b/pkg/test_runner/lib/src/multitest.dart
index fad45a9..0031d5e 100644
--- a/pkg/test_runner/lib/src/multitest.dart
+++ b/pkg/test_runner/lib/src/multitest.dart
@@ -69,7 +69,6 @@
 /// ddd //# 07: static type warning
 /// fff
 /// ```
-import "dart:async";
 import "dart:io";
 
 import "path.dart";
@@ -171,9 +170,9 @@
 ///
 /// Writes the resulting tests to [outputDir] and returns a list of [TestFile]s
 /// for each of those generated tests.
-Future<List<TestFile>> splitMultitest(
+List<TestFile> splitMultitest(
     TestFile multitest, String outputDir, Path suiteDir,
-    {bool hotReload}) async {
+    {bool hotReload}) {
   // Each key in the map tests is a multitest tag or "none", and the texts of
   // the generated test is its value.
   var tests = <String, String>{};
@@ -186,7 +185,6 @@
 
   // Copy all the relative imports of the multitest.
   var importsToCopy = _findAllRelativeImports(multitest.path);
-  var futureCopies = <Future>[];
   for (var relativeImport in importsToCopy) {
     var importPath = Path(relativeImport);
     // Make sure the target directory exists.
@@ -197,14 +195,11 @@
 
     // Copy file. Because some test suites may be read-only, we don't
     // want to copy the permissions, so we create the copy by writing.
-    final source = File(sourceDir.join(importPath).toNativePath()).openRead();
-    final target = File(targetDir.join(importPath).toNativePath()).openWrite();
-    futureCopies.add(source.cast<List<int>>().pipe(target));
+    var contents =
+        File(sourceDir.join(importPath).toNativePath()).readAsBytesSync();
+    File(targetDir.join(importPath).toNativePath()).writeAsBytesSync(contents);
   }
 
-  // Wait until all imports are copied before scheduling test cases.
-  await Future.wait(futureCopies);
-
   var baseFilename = multitest.path.filenameWithoutExtension;
 
   var testFiles = <TestFile>[];
diff --git a/pkg/test_runner/lib/src/process_queue.dart b/pkg/test_runner/lib/src/process_queue.dart
index 01a2fb1..37941de 100644
--- a/pkg/test_runner/lib/src/process_queue.dart
+++ b/pkg/test_runner/lib/src/process_queue.dart
@@ -235,17 +235,12 @@
     // system, generate tests, and search test files for options.
     var testCache = <String, List<TestFile>>{};
 
-    var iterator = testSuites.iterator;
-    void enqueueNextSuite() {
-      if (!iterator.moveNext()) {
-        // We're finished with building the dependency graph.
-        graph.seal();
-      } else {
-        iterator.current.forEachTest(_newTest, testCache, enqueueNextSuite);
-      }
+    for (var suite in testSuites) {
+      suite.findTestCases(_add, testCache);
     }
 
-    enqueueNextSuite();
+    // We're finished with building the dependency graph.
+    graph.seal();
   }
 
   /// Adds a test case to the list of active test cases, and adds its commands
@@ -259,14 +254,14 @@
   /// command of the previous copy of the test case. This dependency is
   /// marked as a "timingDependency", so that it doesn't depend on the previous
   /// test completing successfully, just on it completing.
-  void _newTest(TestCase testCase) {
+  void _add(TestCase testCase) {
     Node<Command> lastNode;
     for (var i = 0; i < testCase.configuration.repeat; ++i) {
       if (i > 0) {
         testCase = testCase.indexedCopy(i);
       }
       remainingTestCases.add(testCase);
-      bool isFirstCommand = true;
+      var isFirstCommand = true;
       for (var command in testCase.commands) {
         // Make exactly *one* node in the dependency graph for every command.
         // This ensures that we never have two commands c1 and c2 in the graph
@@ -280,7 +275,7 @@
           command2node[command] = node;
           command2testCases[command] = <TestCase>[];
         }
-        // Keep mapping from command to all testCases that refer to it
+        // Keep mapping from command to all testCases that refer to it.
         command2testCases[command].add(testCase);
 
         lastNode = node;
diff --git a/pkg/test_runner/lib/src/runtime_configuration.dart b/pkg/test_runner/lib/src/runtime_configuration.dart
index 04f4629..da7d327 100644
--- a/pkg/test_runner/lib/src/runtime_configuration.dart
+++ b/pkg/test_runner/lib/src/runtime_configuration.dart
@@ -97,13 +97,10 @@
   bool get shouldSkipNegativeTests => false;
 
   /// Returns the path to the Dart VM executable.
-  String get dartVmBinaryFileName {
-    // Controlled by user with the option "--dart".
-    var dartExecutable = _configuration.dartPath ?? dartVmExecutableFileName;
-
-    TestUtils.ensureExists(dartExecutable, _configuration);
-    return dartExecutable;
-  }
+  ///
+  /// Controlled by user with the option "--dart".
+  String get dartVmBinaryFileName =>
+      _configuration.dartPath ?? dartVmExecutableFileName;
 
   String get dartVmExecutableFileName {
     return _configuration.useSdk
diff --git a/pkg/test_runner/lib/src/test_case.dart b/pkg/test_runner/lib/src/test_case.dart
index 2b153eaa..0dfc63f 100644
--- a/pkg/test_runner/lib/src/test_case.dart
+++ b/pkg/test_runner/lib/src/test_case.dart
@@ -14,7 +14,6 @@
 import 'configuration.dart';
 import 'output_log.dart';
 import 'process_queue.dart';
-import 'repository.dart';
 import 'test_file.dart';
 import 'utils.dart';
 
@@ -55,28 +54,20 @@
 
   TestConfiguration configuration;
   String displayName;
-  int hash = 0;
   Set<Expectation> expectedOutcomes;
   final TestFile testFile;
 
   TestCase(this.displayName, this.commands, this.configuration,
       this.expectedOutcomes,
-      {TestFile testFile})
-      : testFile = testFile {
+      {this.testFile}) {
     // A test case should do something.
     assert(commands.isNotEmpty);
-
-    if (testFile != null) {
-      hash = (testFile.originPath?.relativeTo(Repository.dir)?.toString())
-          .hashCode;
-    }
   }
 
   TestCase indexedCopy(int index) {
     var newCommands = commands.map((c) => c.indexedCopy(index)).toList();
     return TestCase(displayName, newCommands, configuration, expectedOutcomes,
-        testFile: testFile)
-      ..hash = hash;
+        testFile: testFile);
   }
 
   bool get hasRuntimeError => testFile?.hasRuntimeError ?? false;
diff --git a/pkg/test_runner/lib/src/test_configurations.dart b/pkg/test_runner/lib/src/test_configurations.dart
index 5123fd1..674c55c 100644
--- a/pkg/test_runner/lib/src/test_configurations.dart
+++ b/pkg/test_runner/lib/src/test_configurations.dart
@@ -116,7 +116,7 @@
     // If we specifically pass in a suite only run that.
     if (configuration.suiteDirectory != null) {
       var suitePath = Path(configuration.suiteDirectory);
-      testSuites.add(PKGTestSuite(configuration, suitePath));
+      testSuites.add(PackageTestSuite(configuration, suitePath));
     } else {
       for (var testSuiteDir in TEST_SUITE_DIRECTORIES) {
         var name = testSuiteDir.filename;
diff --git a/pkg/test_runner/lib/src/test_file.dart b/pkg/test_runner/lib/src/test_file.dart
index f24719a..f908add 100644
--- a/pkg/test_runner/lib/src/test_file.dart
+++ b/pkg/test_runner/lib/src/test_file.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 import 'dart:io';
 
+import 'feature.dart';
 import 'path.dart';
 import 'static_error.dart';
 
@@ -23,21 +24,29 @@
 List<String> _splitWords(String s) =>
     s.split(' ').where((e) => e != '').toList();
 
-List<String> _parseOption(String filePath, String contents, String name,
+List<T> _parseOption<T>(
+    String filePath, String contents, String name, T Function(String) convert,
     {bool allowMultiple = false}) {
   var matches = RegExp('// $name=(.*)').allMatches(contents);
   if (!allowMultiple && matches.length > 1) {
     throw Exception('More than one "// $name=" line in test $filePath');
   }
 
-  var options = <String>[];
+  var options = <T>[];
   for (var match in matches) {
-    options.addAll(_splitWords(match[1]));
+    for (var option in _splitWords(match[1])) {
+      options.add(convert(option));
+    }
   }
 
   return options;
 }
 
+List<String> _parseStringOption(String filePath, String contents, String name,
+        {bool allowMultiple = false}) =>
+    _parseOption<String>(filePath, contents, name, (string) => string,
+        allowMultiple: allowMultiple);
+
 abstract class _TestFileBase {
   /// The test suite directory containing this test.
   final Path _suiteDirectory;
@@ -66,8 +75,20 @@
   /// static error reporting.
   bool get isStaticErrorTest => expectedErrors.isNotEmpty;
 
+  /// A hash code used to spread tests across shards.
+  int get shardHash {
+    // The VM C++ unit tests have a special fake TestFile with no suite
+    // directory or path. Don't crash in that case.
+    // TODO(rnystrom): Is there a cleaner solution? Should we use the C++ file
+    // as the path for the TestFile?
+    if (originPath == null) return 0;
+
+    return originPath.relativeTo(_suiteDirectory).toString().hashCode;
+  }
+
   _TestFileBase(this._suiteDirectory, this.path, this.expectedErrors) {
-    assert(path.isAbsolute);
+    // The VM C++ unit tests have a special fake TestFile with no path.
+    if (path != null) assert(path.isAbsolute);
   }
 
   /// The logical name of the test.
@@ -152,6 +173,7 @@
       Path suiteDirectory, String filePath, String contents) {
     if (filePath.endsWith('.dill')) {
       return TestFile._(suiteDirectory, Path(filePath), [],
+          requirements: [],
           vmOptions: [[]],
           sharedOptions: [],
           dart2jsOptions: [],
@@ -171,6 +193,16 @@
           otherResources: []);
     }
 
+    // Required features.
+    var requirements =
+        _parseOption<Feature>(filePath, contents, 'Requirements', (name) {
+      for (var feature in Feature.all) {
+        if (feature.name == name) return feature;
+      }
+
+      throw FormatException('Unknown feature "$name" in test $filePath');
+    });
+
     // VM options.
     var vmOptions = <List<String>>[];
     var matches = _vmOptionsRegExp.allMatches(contents);
@@ -180,14 +212,16 @@
     if (vmOptions.isEmpty) vmOptions.add(<String>[]);
 
     // Other options.
-    var dartOptions = _parseOption(filePath, contents, 'DartOptions');
-    var sharedOptions = _parseOption(filePath, contents, 'SharedOptions');
-    var dart2jsOptions = _parseOption(filePath, contents, 'dart2jsOptions');
-    var ddcOptions = _parseOption(filePath, contents, 'dartdevcOptions');
-    var otherResources =
-        _parseOption(filePath, contents, 'OtherResources', allowMultiple: true);
-    var sharedObjects =
-        _parseOption(filePath, contents, 'SharedObjects', allowMultiple: true);
+    var dartOptions = _parseStringOption(filePath, contents, 'DartOptions');
+    var sharedOptions = _parseStringOption(filePath, contents, 'SharedOptions');
+    var dart2jsOptions =
+        _parseStringOption(filePath, contents, 'dart2jsOptions');
+    var ddcOptions = _parseStringOption(filePath, contents, 'dartdevcOptions');
+    var otherResources = _parseStringOption(
+        filePath, contents, 'OtherResources',
+        allowMultiple: true);
+    var sharedObjects = _parseStringOption(filePath, contents, 'SharedObjects',
+        allowMultiple: true);
 
     // Environment.
     Map<String, String> environment;
@@ -292,6 +326,7 @@
         hasStaticWarning: contents.contains("@static-warning"),
         hasCrash: false,
         subtestNames: subtestNames,
+        requirements: requirements,
         sharedOptions: sharedOptions,
         dartOptions: dartOptions,
         dart2jsOptions: dart2jsOptions,
@@ -314,6 +349,7 @@
         isMultitest = false,
         isMultiHtmlTest = false,
         subtestNames = [],
+        requirements = [],
         sharedOptions = [],
         dartOptions = [],
         dart2jsOptions = [],
@@ -335,6 +371,7 @@
       this.hasStaticWarning,
       this.hasCrash,
       this.subtestNames,
+      this.requirements,
       this.sharedOptions,
       this.dartOptions,
       this.dart2jsOptions,
@@ -364,6 +401,14 @@
   final bool hasCrash;
 
   final List<String> subtestNames;
+
+  /// The features that a test configuration must support in order to run this
+  /// test.
+  ///
+  /// If the current configuration does not support one or more of these
+  /// requirements, the test is implicitly skipped.
+  final List<Feature> requirements;
+
   final List<String> sharedOptions;
   final List<String> dartOptions;
   final List<String> dart2jsOptions;
@@ -398,6 +443,7 @@
   hasStaticWarning: $hasStaticWarning
   hasCrash: $hasCrash
   subtestNames: $subtestNames
+  requirements: $requirements
   sharedOptions: $sharedOptions
   dartOptions: $dartOptions
   dart2jsOptions: $dart2jsOptions
@@ -437,6 +483,7 @@
   String get packageRoot => _origin.packageRoot;
   String get packages => _origin.packages;
 
+  List<Feature> get requirements => _origin.requirements;
   List<String> get dart2jsOptions => _origin.dart2jsOptions;
   List<String> get dartOptions => _origin.dartOptions;
   List<String> get ddcOptions => _origin.ddcOptions;
diff --git a/pkg/test_runner/lib/src/test_suite.dart b/pkg/test_runner/lib/src/test_suite.dart
index f2fb6c7..08fc09b 100644
--- a/pkg/test_runner/lib/src/test_suite.dart
+++ b/pkg/test_runner/lib/src/test_suite.dart
@@ -10,7 +10,6 @@
 ///   and creating [TestCase]s for those files that meet the relevant criteria.
 /// - Preparing tests, including copying files and frameworks to temporary
 ///   directories, and computing the command line and arguments to be run.
-import 'dart:async';
 import 'dart:io';
 import 'dart:math';
 
@@ -32,9 +31,6 @@
 
 typedef TestCaseEvent = void Function(TestCase testCase);
 
-/// A simple function that tests [arg] and returns `true` or `false`.
-typedef Predicate<T> = bool Function(T arg);
-
 typedef CreateTest = void Function(Path filePath, Path originTestPath,
     {bool hasSyntaxError,
     bool hasCompileError,
@@ -44,57 +40,6 @@
 
 typedef VoidFunction = void Function();
 
-/// Calls [function] asynchronously. Returns a future that completes with the
-/// result of the function. If the function is `null`, returns a future that
-/// completes immediately with `null`.
-Future asynchronously<T>(T function()) {
-  if (function == null) return Future<T>.value(null);
-
-  var completer = Completer<T>();
-  Timer.run(() => completer.complete(function()));
-
-  return completer.future;
-}
-
-/// A completer that waits until all added [Future]s complete.
-// TODO(rnystrom): Copied from web_components. Remove from here when it gets
-// added to dart:core. (See #6626.)
-class FutureGroup {
-  static const _finished = -1;
-  int _pending = 0;
-  final Completer<List> _completer = Completer();
-  final List<Future> futures = [];
-  bool wasCompleted = false;
-
-  /// Wait for [task] to complete (assuming this barrier has not already been
-  /// marked as completed, otherwise you'll get an exception indicating that a
-  /// future has already been completed).
-  void add(Future task) {
-    if (_pending == _finished) {
-      throw Exception("FutureFutureAlreadyCompleteException");
-    }
-    _pending++;
-    var handledTaskFuture = task.catchError((e, StackTrace s) {
-      if (!wasCompleted) {
-        _completer.completeError(e, s);
-        wasCompleted = true;
-      }
-    }).then((_) {
-      _pending--;
-      if (_pending == 0) {
-        _pending = _finished;
-        if (!wasCompleted) {
-          _completer.complete(futures);
-          wasCompleted = true;
-        }
-      }
-    });
-    futures.add(handledTaskFuture);
-  }
-
-  Future<List> get future => _completer.future;
-}
-
 /// A TestSuite represents a collection of tests.  It creates a [TestCase]
 /// object for each test to be run, and passes the test cases to a callback.
 ///
@@ -106,7 +51,6 @@
   final List<String> statusFilePaths;
 
   /// This function is set by subclasses before enqueueing starts.
-  Function doTest;
   Map<String, String> _environmentOverrides;
 
   TestSuite(this.configuration, this.suiteName, this.statusFilePaths) {
@@ -139,28 +83,26 @@
     return name;
   }
 
-  /// Call the callback function onTest with a [TestCase] argument for each
-  /// test in the suite.  When all tests have been processed, call [onDone].
+  /// Calls [onTest] with each [TestCase] produced by the suite for the
+  /// current configuration.
   ///
   /// The [testCache] argument provides a persistent store that can be used to
   /// cache information about the test suite, so that directories do not need
   /// to be listed each time.
-  Future forEachTest(
-      TestCaseEvent onTest, Map<String, List<TestFile>> testCache,
-      [VoidFunction onDone]);
+  void findTestCases(
+      TestCaseEvent onTest, Map<String, List<TestFile>> testCache);
 
-  /// This function is called for every TestCase of this test suite. It:
+  /// Creates a [TestCase] and passes it to [onTest] if there is a relevant
+  /// test to run for [testFile] in the current configuration.
   ///
-  /// - Handles sharding.
-  /// - Updates [SummaryReport].
-  /// - Handle skip markers.
-  /// - Tests if the selector matches.
-  ///
-  /// and enqueue the test if necessary.
-  void enqueueNewTestCase(TestFile testFile, String fullName,
-      List<Command> commands, Set<Expectation> expectations) {
+  /// This handles skips, shards, selector matching, and updating the
+  /// [SummaryReport].
+  void _addTestCase(TestFile testFile, String fullName, List<Command> commands,
+      Set<Expectation> expectations, TestCaseEvent onTest) {
     var displayName = '$suiteName/$fullName';
 
+    if (!_isRelevantTest(testFile, displayName, expectations)) return;
+
     // If the test is not going to be run at all, then a RuntimeError,
     // MissingRuntimeError or Timeout will never occur.
     // Instead, treat that as Pass.
@@ -173,51 +115,70 @@
       if (expectations.isEmpty) expectations.add(Expectation.pass);
     }
 
-    var negative = testFile != null && isNegative(testFile);
     var testCase = TestCase(displayName, commands, configuration, expectations,
         testFile: testFile);
-    if (negative &&
-        configuration.runtimeConfiguration.shouldSkipNegativeTests) {
-      return;
-    }
-
-    // Handle sharding based on the original test path (i.e. all multitests
-    // of a given original test belong to the same shard)
-    if (configuration.shardCount > 1 &&
-        testCase.hash % configuration.shardCount != configuration.shard - 1) {
-      return;
-    }
-
-    // Test if the selector includes this test.
-    var pattern = configuration.selectors[suiteName];
-    if (!pattern.hasMatch(displayName)) {
-      return;
-    }
-    if (configuration.testList != null &&
-        !configuration.testList.contains(displayName)) {
-      return;
-    }
-
-    if (configuration.hotReload || configuration.hotReloadRollback) {
-      // Handle reload special cases.
-      if (expectations.contains(Expectation.compileTimeError) ||
-          testCase.hasCompileError) {
-        // Running a test that expects a compilation error with hot reloading
-        // is redundant with a regular run of the test.
-        return;
-      }
-    }
 
     // Update Summary report.
     if (configuration.printReport) {
       summaryReport.add(testCase);
     }
 
-    // Handle skipped tests.
+    if (!_shouldSkipTest(expectations)) {
+      onTest(testCase);
+    }
+  }
+
+  /// Whether it is meaningful to run [testFile] with [expectations] under the
+  /// current configuration.
+  ///
+  /// Does not take skips into account, but does "skip" tests for other
+  /// fundamental reasons.
+  bool _isRelevantTest(
+      TestFile testFile, String displayName, Set<Expectation> expectations) {
+    // Test if the selector includes this test.
+    var pattern = configuration.selectors[suiteName];
+    if (!pattern.hasMatch(displayName)) {
+      return false;
+    }
+
+    if (configuration.testList != null &&
+        !configuration.testList.contains(displayName)) {
+      return false;
+    }
+
+    if (isNegative(testFile) &&
+        configuration.runtimeConfiguration.shouldSkipNegativeTests) {
+      return false;
+    }
+
+    // Handle sharding based on the original test path. All multitests of a
+    // given original test belong to the same shard.
+    if (configuration.shardCount > 1 &&
+        testFile.shardHash % configuration.shardCount !=
+            configuration.shard - 1) {
+      return false;
+    }
+
+    if (configuration.hotReload || configuration.hotReloadRollback) {
+      // Handle reload special cases.
+      if (expectations.contains(Expectation.compileTimeError) ||
+          testFile.hasCompileError) {
+        // Running a test that expects a compilation error with hot reloading
+        // is redundant with a regular run of the test.
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  /// Whether a test with [expectations] should be skipped under the current
+  /// configuration.
+  bool _shouldSkipTest(Set<Expectation> expectations) {
     if (expectations.contains(Expectation.skip) ||
         expectations.contains(Expectation.skipByDesign) ||
         expectations.contains(Expectation.skipSlow)) {
-      return;
+      return true;
     }
 
     if (configuration.fastTestsOnly &&
@@ -225,10 +186,10 @@
             expectations.contains(Expectation.skipSlow) ||
             expectations.contains(Expectation.timeout) ||
             expectations.contains(Expectation.dartkTimeout))) {
-      return;
+      return true;
     }
 
-    doTest(testCase);
+    return false;
   }
 
   bool isNegative(TestFile testFile) =>
@@ -316,21 +277,15 @@
     }
   }
 
-  Future<Null> forEachTest(TestCaseEvent onTest, Map testCache,
-      [VoidFunction onDone]) async {
-    doTest = onTest;
-
+  void findTestCases(TestCaseEvent onTest, Map testCache) {
     var statusFiles =
         statusFilePaths.map((statusFile) => "$dartDir/$statusFile").toList();
     var expectations = ExpectationSet.read(statusFiles, configuration);
 
     try {
-      for (VMUnitTest test in await _listTests(hostRunnerPath)) {
-        _addTest(expectations, test);
+      for (var test in _listTests(hostRunnerPath)) {
+        _addTest(expectations, test, onTest);
       }
-
-      doTest = null;
-      if (onDone != null) onDone();
     } catch (error, s) {
       print("Fatal error occurred: $error");
       print(s);
@@ -338,7 +293,8 @@
     }
   }
 
-  void _addTest(ExpectationSet testExpectations, VMUnitTest test) {
+  void _addTest(
+      ExpectationSet testExpectations, VMUnitTest test, TestCaseEvent onTest) {
     var fullName = 'cc/${test.name}';
     var expectations = testExpectations.expectations(fullName);
 
@@ -375,11 +331,11 @@
 
     var command = ProcessCommand(
         'run_vm_unittest', targetRunnerPath, args, environmentOverrides);
-    enqueueNewTestCase(testFile, fullName, [command], expectations);
+    _addTestCase(testFile, fullName, [command], expectations, onTest);
   }
 
-  Future<Iterable<VMUnitTest>> _listTests(String runnerPath) async {
-    var result = await Process.run(runnerPath, ["--list"]);
+  Iterable<VMUnitTest> _listTests(String runnerPath) {
+    var result = Process.runSync(runnerPath, ["--list"]);
     if (result.exitCode != 0) {
       throw "Failed to list tests: '$runnerPath --list'. "
           "Process exited with ${result.exitCode}";
@@ -407,8 +363,6 @@
 /// directory, and creates [TestCase]s that compile and/or run them.
 class StandardTestSuite extends TestSuite {
   final Path suiteDir;
-  ExpectationSet testExpectations;
-  List<TestFile> cachedTests;
   final Path dartDir;
   final bool listRecursively;
   final List<String> extraVmOptions;
@@ -470,8 +424,8 @@
     _selectorFilenameRegExp = RegExp(pattern);
   }
 
-  /// Creates a test suite whose file organization matches an expected structure.
-  /// To use this, your suite should look like:
+  /// Creates a test suite whose file organization matches an expected
+  /// structure. To use this, your suite should look like:
   ///
   ///     dart/
   ///       path/
@@ -490,7 +444,7 @@
   ///
   /// If you follow that convention, then you can construct one of these like:
   ///
-  /// new StandardTestSuite.forDirectory(configuration, 'path/to/mytestsuite');
+  ///     StandardTestSuite.forDirectory(configuration, 'path/to/mytestsuite');
   ///
   /// instead of having to create a custom [StandardTestSuite] subclass. In
   /// particular, if you add 'path/to/mytestsuite' to [TEST_SUITE_DIRECTORIES]
@@ -524,64 +478,58 @@
 
   List<String> additionalOptions(Path filePath) => [];
 
-  Future forEachTest(
-      TestCaseEvent onTest, Map<String, List<TestFile>> testCache,
-      [VoidFunction onDone]) async {
-    doTest = onTest;
-    testExpectations = readExpectations();
+  void findTestCases(
+      TestCaseEvent onTest, Map<String, List<TestFile>> testCache) {
+    var expectations = _readExpectations();
 
-    // Check if we have already found and generated the tests for this suite.
-    if (!testCache.containsKey(suiteName)) {
-      cachedTests = testCache[suiteName] = <TestFile>[];
-      await enqueueTests();
-    } else {
-      for (var testFile in testCache[suiteName]) {
-        enqueueTestCaseFromTestFile(testFile);
-      }
+    // Check if we have already found the test files for this suite.
+    var testFiles = testCache[suiteName];
+    if (testFiles == null) {
+      testFiles = [...findTests()];
+      testCache[suiteName] = testFiles;
     }
-    testExpectations = null;
-    cachedTests = null;
-    doTest = null;
-    if (onDone != null) onDone();
+
+    // Produce test cases for each test file.
+    for (var testFile in testFiles) {
+      _testCasesFromTestFile(testFile, expectations, onTest);
+    }
+  }
+
+  /// Walks the file system to find all test files relevant to this test suite.
+  Iterable<TestFile> findTests() {
+    var dir = Directory(suiteDir.toNativePath());
+    if (!dir.existsSync()) {
+      print('Directory containing tests missing: ${suiteDir.toNativePath()}');
+      return const [];
+    }
+
+    return _searchDirectory(dir);
   }
 
   /// Reads the status files and completes with the parsed expectations.
-  ExpectationSet readExpectations() {
-    var statusFiles = statusFilePaths.where((String statusFilePath) {
-      var file = File(dartDir.append(statusFilePath).toNativePath());
-      return file.existsSync();
-    }).map((statusFilePath) {
-      return dartDir.append(statusFilePath).toNativePath();
-    }).toList();
+  ExpectationSet _readExpectations() {
+    var statusFiles = <String>[];
+    for (var relativePath in statusFilePaths) {
+      var file = File(dartDir.append(relativePath).toNativePath());
+      if (!file.existsSync()) continue;
+      statusFiles.add(file.path);
+    }
 
     return ExpectationSet.read(statusFiles, configuration);
   }
 
-  Future enqueueTests() {
-    Directory dir = Directory(suiteDir.toNativePath());
-    return dir.exists().then((exists) {
-      if (!exists) {
-        print('Directory containing tests missing: ${suiteDir.toNativePath()}');
-        return Future.value(null);
-      } else {
-        var group = FutureGroup();
-        enqueueDirectory(dir, group);
-        return group.future;
-      }
-    });
+  /// Looks for test files in [directory].
+  Iterable<TestFile> _searchDirectory(Directory directory) sync* {
+    for (var entry in directory.listSync(recursive: listRecursively)) {
+      if (entry is File) yield* _processFile(entry.path);
+    }
   }
 
-  void enqueueDirectory(Directory dir, FutureGroup group) {
-    var lister = dir
-        .list(recursive: listRecursively)
-        .where((fse) => fse is File)
-        .forEach((FileSystemEntity entity) {
-      enqueueFile((entity as File).path, group);
-    });
-    group.add(lister);
-  }
-
-  void enqueueFile(String filePath, FutureGroup group) {
+  /// Gets the set of [TestFile]s based on the source file at [filePath].
+  ///
+  /// This may produce zero [TestFile]s if [filePath] isn't a test. It may
+  /// produce more than one if the file is a multitest.
+  Iterable<TestFile> _processFile(String filePath) sync* {
     // This is an optimization to avoid scanning and generating extra tests.
     // The definitive check against configuration.testList is performed in
     // TestSuite.enqueueNewTestCase().
@@ -598,29 +546,31 @@
     var testFile = TestFile.read(suiteDir, filePath);
 
     if (testFile.isMultitest) {
-      group.add(splitMultitest(testFile, buildDir, suiteDir,
-              hotReload:
-                  configuration.hotReload || configuration.hotReloadRollback)
-          .then((splitTests) {
-        for (var test in splitTests) {
-          cachedTests.add(test);
-          enqueueTestCaseFromTestFile(test);
-        }
-      }));
+      for (var test in splitMultitest(testFile, buildDir, suiteDir,
+          hotReload:
+              configuration.hotReload || configuration.hotReloadRollback)) {
+        yield test;
+      }
     } else {
-      cachedTests.add(testFile);
-      enqueueTestCaseFromTestFile(testFile);
+      yield testFile;
     }
   }
 
-  void enqueueTestCaseFromTestFile(TestFile testFile) {
-    // Static error tests are currently skipped on every implementation except
-    // analyzer and Fasta.
+  /// Calls [onTest] with every [TestCase] that should be produced from
+  /// [testFile].
+  ///
+  /// This will generally be one or no tests if the test should be skipped but
+  /// may be more if [testFile] is a browser multitest or has multiple VM
+  /// options.
+  void _testCasesFromTestFile(
+      TestFile testFile, ExpectationSet expectations, TestCaseEvent onTest) {
+    // Static error tests are skipped on every implementation except analyzer
+    // and Fasta.
     // TODO(rnystrom): Should other configurations that use CFE support static
     // error tests?
     // TODO(rnystrom): Skipping this here is a little unusual because most
-    // skips are handled in enqueueStandardTest(). However, if the configuration
-    // is running on browser, calling enqueueStandardTest() will try to create
+    // skips are handled in _addTestCase(). However, if the configuration
+    // is running on a browser, calling _addTestCase() will try to create
     // a set of commands which ultimately causes an exception in
     // DummyRuntimeConfiguration. This avoids that.
     if (testFile.isStaticErrorTest &&
@@ -629,12 +579,17 @@
       return;
     }
 
+    // The configuration must support everything the test needs.
+    if (!configuration.supportedFeatures.containsAll(testFile.requirements)) {
+      return;
+    }
+
     if (configuration.compilerConfiguration.hasCompiler &&
         (testFile.hasCompileError || testFile.isStaticErrorTest)) {
       // If a compile-time error is expected, and we're testing a
       // compiler, we never need to attempt to run the program (in a
       // browser or otherwise).
-      enqueueStandardTest(testFile);
+      _enqueueStandardTest(testFile, expectations, onTest);
     } else if (configuration.runtime.isBrowser) {
       var expectationsMap = <String, Set<Expectation>>{};
 
@@ -646,20 +601,21 @@
         expectationsMap = <String, Set<Expectation>>{};
         for (var subtest in subtestNames) {
           expectationsMap[subtest] =
-              testExpectations.expectations('${testFile.name}/$subtest');
+              expectations.expectations('${testFile.name}/$subtest');
         }
       } else {
         expectationsMap[testFile.name] =
-            testExpectations.expectations(testFile.name);
+            expectations.expectations(testFile.name);
       }
 
-      _enqueueBrowserTest(testFile, expectationsMap);
+      _enqueueBrowserTest(testFile, expectationsMap, onTest);
     } else {
-      enqueueStandardTest(testFile);
+      _enqueueStandardTest(testFile, expectations, onTest);
     }
   }
 
-  void enqueueStandardTest(TestFile testFile) {
+  void _enqueueStandardTest(
+      TestFile testFile, ExpectationSet expectations, TestCaseEvent onTest) {
     var commonArguments = _commonArgumentsFromFile(testFile);
 
     var vmOptionsList = getVmOptions(testFile);
@@ -674,8 +630,8 @@
         allVmOptions = vmOptions.toList()..addAll(extraVmOptions);
       }
 
-      var expectations = testExpectations.expectations(testFile.name);
-      var isCrashExpected = expectations.contains(Expectation.crash);
+      var testExpectations = expectations.expectations(testFile.name);
+      var isCrashExpected = testExpectations.contains(Expectation.crash);
       var commands = _makeCommands(testFile, vmOptionsVariant, allVmOptions,
           commonArguments, isCrashExpected);
       var variantTestName = testFile.name;
@@ -683,7 +639,8 @@
         variantTestName = "${testFile.name}/$vmOptionsVariant";
       }
 
-      enqueueNewTestCase(testFile, variantTestName, commands, expectations);
+      _addTestCase(
+          testFile, variantTestName, commands, testExpectations, onTest);
     }
   }
 
@@ -811,8 +768,8 @@
   /// In order to handle browser multitests, [expectations] is a map of subtest
   /// names to expectation sets. If the test is not a multitest, the map has
   /// a single key, `testFile.name`.
-  void _enqueueBrowserTest(
-      TestFile testFile, Map<String, Set<Expectation>> expectations) {
+  void _enqueueBrowserTest(TestFile testFile,
+      Map<String, Set<Expectation>> expectations, TestCaseEvent onTest) {
     var tempDir = createOutputDirectory(testFile.path);
     var compilationTempDir = createCompilationOutputDirectory(testFile.path);
     var nameNoExt = testFile.path.filenameWithoutExtension;
@@ -879,11 +836,12 @@
             '${testFile.name}/$subtestName',
             subtestName,
             expectations[subtestName],
-            htmlPath);
+            htmlPath,
+            onTest);
       }
     } else {
       _enqueueSingleBrowserTest(commands, testFile, testFile.name, null,
-          expectations[testFile.name], htmlPath);
+          expectations[testFile.name], htmlPath, onTest);
     }
   }
 
@@ -894,7 +852,8 @@
       String testName,
       String subtestName,
       Set<Expectation> expectations,
-      String htmlPath) {
+      String htmlPath,
+      TestCaseEvent onTest) {
     // Construct the command that executes the browser test.
     commands = commands.toList();
 
@@ -906,7 +865,7 @@
 
     var fullName = testName;
     if (subtestName != null) fullName += "/$subtestName";
-    enqueueNewTestCase(testFile, fullName, commands, expectations);
+    _addTestCase(testFile, fullName, commands, expectations, onTest);
   }
 
   List<String> _commonArgumentsFromFile(TestFile testFile) {
@@ -976,26 +935,26 @@
 
 /// Used for testing packages in one-off settings, i.e., we pass in the actual
 /// directory that we want to test.
-class PKGTestSuite extends StandardTestSuite {
-  PKGTestSuite(TestConfiguration configuration, Path directoryPath)
+class PackageTestSuite extends StandardTestSuite {
+  PackageTestSuite(TestConfiguration configuration, Path directoryPath)
       : super(configuration, directoryPath.filename, directoryPath,
             ["$directoryPath/.status"],
             recursive: true);
 
-  void _enqueueBrowserTest(
-      TestFile testFile, Map<String, Set<Expectation>> expectations) {
+  void _enqueueBrowserTest(TestFile testFile,
+      Map<String, Set<Expectation>> expectations, TestCaseEvent onTest) {
     var dir = testFile.path.directoryPath;
     var nameNoExt = testFile.path.filenameWithoutExtension;
     var customHtmlPath = dir.append('$nameNoExt.html');
     var customHtml = File(customHtmlPath.toNativePath());
     if (!customHtml.existsSync()) {
-      super._enqueueBrowserTest(testFile, expectations);
+      super._enqueueBrowserTest(testFile, expectations, onTest);
     } else {
       var fullPath = _createUrlPathFromFile(customHtmlPath);
       var command = Command.browserTest(fullPath, configuration,
           retry: !isNegative(testFile));
-      enqueueNewTestCase(
-          testFile, testFile.name, [command], expectations[testFile.name]);
+      _addTestCase(testFile, testFile.name, [command],
+          expectations[testFile.name], onTest);
     }
   }
 }
@@ -1015,15 +974,13 @@
   List<String> additionalOptions(Path filePath, {bool showSdkWarnings}) =>
       const ['--fatal-warnings', '--fatal-type-errors', '--sdk-warnings'];
 
-  Future enqueueTests() {
-    var group = FutureGroup();
-
+  Iterable<TestFile> findTests() {
     var dir = Directory(suiteDir.append('lib').toNativePath());
     if (dir.existsSync()) {
-      enqueueDirectory(dir, group);
+      return _searchDirectory(dir);
     }
 
-    return group.future;
+    return const [];
   }
 
   bool isTestFile(String filename) {
diff --git a/pkg/test_runner/test/test_file_test.dart b/pkg/test_runner/test/test_file_test.dart
index b35c116..7418bda 100644
--- a/pkg/test_runner/test/test_file_test.dart
+++ b/pkg/test_runner/test/test_file_test.dart
@@ -5,10 +5,13 @@
 
 import 'package:expect/expect.dart';
 
+import 'package:test_runner/src/feature.dart';
 import 'package:test_runner/src/path.dart';
 import 'package:test_runner/src/static_error.dart';
 import 'package:test_runner/src/test_file.dart';
 
+import 'utils.dart';
+
 // Note: This test file validates how some of the special markers used by the
 // test runner are parsed. But this test is also run *by* that same test
 // runner, and we don't want it to see the markers inside the string literals
@@ -27,11 +30,12 @@
   testParseErrorExpectations();
   testName();
   testMultitest();
+  testShardHash();
 }
 
 void testParseDill() {
   // Handles ".dill" files.
-  var file = parse("", path: "test.dill");
+  var file = parseTestFile("", path: "test.dill");
   Expect.isNotNull(file.vmOptions);
   Expect.equals(1, file.vmOptions.length);
   Expect.listEquals(<String>[], file.vmOptions.first);
@@ -57,7 +61,7 @@
 
 void testParseVMOptions() {
   expectVMOptions(String source, List<List<String>> expected) {
-    var file = parse(source);
+    var file = parseTestFile(source);
     Expect.isNotNull(file.vmOptions);
     Expect.equals(expected.length, file.vmOptions.length);
     for (var i = 0; i < expected.length; i++) {
@@ -85,29 +89,31 @@
 
 void testParseOtherOptions() {
   // No options.
-  var file = parse("");
+  var file = parseTestFile("");
   Expect.listEquals(<String>[], file.dartOptions);
   Expect.listEquals(<String>[], file.sharedOptions);
   Expect.listEquals(<String>[], file.dart2jsOptions);
   Expect.listEquals(<String>[], file.ddcOptions);
   Expect.listEquals(<String>[], file.otherResources);
   Expect.listEquals(<String>[], file.sharedObjects);
+  Expect.listEquals(<String>[], file.requirements);
 
   // Single options split into words.
-  file = parse("""
+  file = parseTestFile("""
   /\/ DartOptions=dart options
   /\/ SharedOptions=shared options
   /\/ dart2jsOptions=dart2js options
   /\/ dartdevcOptions=ddc options
   /\/ OtherResources=other resources
   /\/ SharedObjects=shared objects
+  /\/ Requirements=nnbd nnbd-strong
   """);
   Expect.listEquals(["dart", "options"], file.dartOptions);
   Expect.listEquals(["shared", "options"], file.sharedOptions);
   Expect.listEquals(["dart2js", "options"], file.dart2jsOptions);
   Expect.listEquals(["ddc", "options"], file.ddcOptions);
   Expect.listEquals(["other", "resources"], file.otherResources);
-  Expect.listEquals(["shared", "objects"], file.sharedObjects);
+  Expect.listEquals([Feature.nnbd, Feature.nnbdStrong], file.requirements);
 
   // Disallows multiple lines for some options.
   expectParseThrows("""
@@ -126,9 +132,13 @@
   /\/ dartdevcOptions=first
   /\/ dartdevcOptions=second
   """);
+  expectParseThrows("""
+  /\/ Requirements=nnbd
+  /\/ Requirements=nnbd-strong
+  """);
 
   // Merges multiple lines for others.
-  file = parse("""
+  file = parseTestFile("""
   /\/ OtherResources=other resources
   /\/ OtherResources=even more
   /\/ SharedObjects=shared objects
@@ -137,22 +147,27 @@
   Expect.listEquals(
       ["other", "resources", "even", "more"], file.otherResources);
   Expect.listEquals(["shared", "objects", "many", "more"], file.sharedObjects);
+
+  // Disallows unrecognized features in requirements.
+  expectParseThrows("""
+  /\/ Requirements=unknown-feature
+  """);
 }
 
 void testParseEnvironment() {
   // No environment.
-  var file = parse("");
+  var file = parseTestFile("");
   Expect.isNull(file.environment);
 
   // Without values.
-  file = parse("""
+  file = parseTestFile("""
   /\/ Environment=some value
   /\/ Environment=another one
   """);
   Expect.mapEquals({"some value": "", "another one": ""}, file.environment);
 
   // With values.
-  file = parse("""
+  file = parseTestFile("""
   /\/ Environment=some value=its value
   /\/ Environment=another one   =   also value
   """);
@@ -163,18 +178,18 @@
 
 void testParsePackages() {
   // No option.
-  var file = parse("");
+  var file = parseTestFile("");
   Expect.isNull(file.packages);
 
   // Single option is converted to a path.
-  file = parse("""
+  file = parseTestFile("""
   /\/ Packages=packages thing
   """);
   Expect.isTrue(
       file.packages.endsWith("${Platform.pathSeparator}packages thing"));
 
   // "none" is left alone.
-  file = parse("""
+  file = parseTestFile("""
   /\/ Packages=none
   """);
   Expect.equals("none", file.packages);
@@ -188,11 +203,11 @@
 
 void testParseMultitest() {
   // Not present.
-  var file = parse("");
+  var file = parseTestFile("");
   Expect.isFalse(file.isMultitest);
 
   // Present.
-  file = parse("""
+  file = parseTestFile("""
   main() {} /\/# 01: compile-time error
   """);
   Expect.isTrue(file.isMultitest);
@@ -200,14 +215,14 @@
 
 void testParseMultiHtmltest() {
   // Not present.
-  var file = parse("");
+  var file = parseTestFile("");
   Expect.isFalse(file.isMultiHtmlTest);
   Expect.listEquals(<String>[], file.subtestNames);
 
   // Present.
   // Note: the "${''}" is to prevent the test runner running *this* test file
   // from parsing it as a multi-HTML test.
-  file = parse("""
+  file = parseTestFile("""
   main() {
     useHtml\IndividualConfiguration();
     group('pixel_manipulation', () {
@@ -225,35 +240,35 @@
 
 void testParseErrorFlags() {
   // Not present.
-  var file = parse("");
+  var file = parseTestFile("");
   Expect.isFalse(file.hasSyntaxError);
   Expect.isFalse(file.hasCompileError);
   Expect.isFalse(file.hasRuntimeError);
   Expect.isFalse(file.hasStaticWarning);
   Expect.isFalse(file.hasCrash);
 
-  file = parse("@syntax\-error");
+  file = parseTestFile("@syntax\-error");
   Expect.isTrue(file.hasSyntaxError);
   Expect.isTrue(file.hasCompileError); // Note: true.
   Expect.isFalse(file.hasRuntimeError);
   Expect.isFalse(file.hasStaticWarning);
   Expect.isFalse(file.hasCrash);
 
-  file = parse("@compile\-error");
+  file = parseTestFile("@compile\-error");
   Expect.isFalse(file.hasSyntaxError);
   Expect.isTrue(file.hasCompileError);
   Expect.isFalse(file.hasRuntimeError);
   Expect.isFalse(file.hasStaticWarning);
   Expect.isFalse(file.hasCrash);
 
-  file = parse("@runtime\-error");
+  file = parseTestFile("@runtime\-error");
   Expect.isFalse(file.hasSyntaxError);
   Expect.isFalse(file.hasCompileError);
   Expect.isTrue(file.hasRuntimeError);
   Expect.isFalse(file.hasStaticWarning);
   Expect.isFalse(file.hasCrash);
 
-  file = parse("@static\-warning");
+  file = parseTestFile("@static\-warning");
   Expect.isFalse(file.hasSyntaxError);
   Expect.isFalse(file.hasCompileError);
   Expect.isFalse(file.hasRuntimeError);
@@ -493,7 +508,7 @@
 }
 
 void testMultitest() {
-  var file = parse("", path: "origin.dart");
+  var file = parseTestFile("", path: "origin.dart");
   Expect.isFalse(file.hasSyntaxError);
   Expect.isFalse(file.hasCompileError);
   Expect.isFalse(file.hasRuntimeError);
@@ -537,22 +552,28 @@
   Expect.isTrue(d.hasStaticWarning);
 }
 
+void testShardHash() {
+  // Test files with paths should successfully return some kind of integer. We
+  // don't want to depend on the hash algorithm, so we can't really be more
+  // specific than that.
+  var testFile = parseTestFile("", path: "a_test.dart");
+  Expect.isTrue(testFile.shardHash is int);
+
+  // VM test files are hard-coded to return hash zero because they don't have a
+  // path to base the hash on.
+  Expect.equals(0, TestFile.vmUnitTest().shardHash);
+}
+
 void expectParseErrorExpectations(String source, List<StaticError> errors) {
-  var file = parse(source);
+  var file = parseTestFile(source);
   Expect.listEquals(errors.map((error) => error.toString()).toList(),
       file.expectedErrors.map((error) => error.toString()).toList());
 }
 
 void expectFormatError(String source) {
-  Expect.throwsFormatException(() => parse(source));
+  Expect.throwsFormatException(() => parseTestFile(source));
 }
 
 void expectParseThrows(String source) {
-  Expect.throws(() => parse(source));
-}
-
-TestFile parse(String source, {String path = "some_test.dart"}) {
-  path = Path(path).absolute.toNativePath();
-  var suiteDirectory = Path(path).directoryPath;
-  return TestFile.parse(suiteDirectory, path, source);
+  Expect.throws(() => parseTestFile(source));
 }
diff --git a/pkg/test_runner/test/test_runner_test.dart b/pkg/test_runner/test/test_runner_test.dart
index 4123612..eea706f 100644
--- a/pkg/test_runner/test/test_runner_test.dart
+++ b/pkg/test_runner/test/test_runner_test.dart
@@ -71,7 +71,7 @@
   CustomTestSuite(TestConfiguration configuration)
       : super(configuration, "CustomTestSuite", []);
 
-  Future forEachTest(TestCaseEvent onTest, Map testCache, [onDone]) async {
+  void findTestCases(TestCaseEvent onTest, Map testCache) {
     void enqueueTestCase(TestCase testCase) {
       TestController.numTests++;
       onTest(testCase);
@@ -89,10 +89,6 @@
     enqueueTestCase(testCaseFail);
     enqueueTestCase(testCaseTimeout);
     enqueueTestCase(testCaseFailUnexpected);
-
-    if (onDone != null) {
-      onDone();
-    }
   }
 
   TestCase _makeNormalTestCase(
diff --git a/pkg/test_runner/test/test_suite_test.dart b/pkg/test_runner/test/test_suite_test.dart
new file mode 100644
index 0000000..30304d1
--- /dev/null
+++ b/pkg/test_runner/test/test_suite_test.dart
@@ -0,0 +1,55 @@
+// 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 'package:test_runner/src/test_file.dart';
+
+import 'utils.dart';
+
+void main() {
+  testNnbdRequirements();
+}
+
+void testNnbdRequirements() {
+  // Note: The backslashes are to avoid the test_runner thinking these are
+  // Requirements markers for this file itself.
+  var testFiles = [
+    parseTestFile("", path: "none_test.dart"),
+    parseTestFile("/\/ Requirements=nnbd", path: "nnbd_test.dart"),
+    parseTestFile("/\/ Requirements=nnbd-legacy", path: "legacy_test.dart"),
+    parseTestFile("/\/ Requirements=nnbd-weak", path: "weak_test.dart"),
+    parseTestFile("/\/ Requirements=nnbd-strong", path: "strong_test.dart"),
+  ];
+
+  expectTestCases(
+      [], testFiles, ["language_2/none_test", "language_2/legacy_test"]);
+
+  expectTestCases(["--nnbd=legacy"], testFiles,
+      ["language_2/none_test", "language_2/legacy_test"]);
+
+  expectTestCases(["--nnbd=weak"], testFiles,
+      ["language_2/none_test", "language_2/nnbd_test", "language_2/weak_test"]);
+
+  expectTestCases(
+      ["--nnbd=strong"],
+      testFiles,
+      [
+        "language_2/none_test",
+        "language_2/nnbd_test",
+        "language_2/strong_test"
+      ]);
+}
+
+void expectTestCases(List<String> options, List<TestFile> testFiles,
+    List<String> expectedCaseNames) {
+  var configuration = makeConfiguration(options);
+  var suite = makeTestSuite(configuration, testFiles);
+
+  var testCaseNames = <String>[];
+  suite.findTestCases((testCase) {
+    testCaseNames.add(testCase.displayName);
+  }, {});
+
+  Expect.listEquals(expectedCaseNames, testCaseNames);
+}
diff --git a/pkg/test_runner/test/utils.dart b/pkg/test_runner/test/utils.dart
new file mode 100644
index 0000000..e3ccc1b
--- /dev/null
+++ b/pkg/test_runner/test/utils.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_runner/src/configuration.dart';
+import 'package:test_runner/src/options.dart';
+import 'package:test_runner/src/path.dart';
+import 'package:test_runner/src/test_file.dart';
+import 'package:test_runner/src/test_suite.dart';
+
+final Path _suiteDirectory = Path("language_2");
+
+TestFile parseTestFile(String source, {String path = "some_test.dart"}) {
+  path = _suiteDirectory.absolute.append(path).toNativePath();
+  return TestFile.parse(_suiteDirectory.absolute, path, source);
+}
+
+// TODO(rnystrom): Would be nice if there was a simpler way to create a
+// configuration for use in unit tests.
+TestConfiguration makeConfiguration(List<String> arguments) =>
+    OptionsParser().parse([...arguments, "language_2"]).first;
+
+/// Creates a [StandardTestSuite] hardcoded to contain [testFiles].
+StandardTestSuite makeTestSuite(
+        TestConfiguration configuration, List<TestFile> testFiles) =>
+    _MockTestSuite(configuration, testFiles);
+
+class _MockTestSuite extends StandardTestSuite {
+  final List<TestFile> _testFiles;
+
+  _MockTestSuite(TestConfiguration configuration, this._testFiles)
+      : super(configuration, "language_2", _suiteDirectory, []);
+
+  @override
+  Iterable<TestFile> findTests() => _testFiles;
+}
diff --git a/pkg/test_runner/tool/co19.dart b/pkg/test_runner/tool/co19.dart
deleted file mode 100644
index 72b7a6d..0000000
--- a/pkg/test_runner/tool/co19.dart
+++ /dev/null
@@ -1,55 +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.
-
-/// Tool for running co19 tests. Used when updating co19.
-///
-/// Currently, this tool is merely a convenience around multiple
-/// invocations of test.dart. Long term, we hope to evolve this into a
-/// script that can automate most of the tasks necessary when updating
-/// co19.
-///
-/// Usage:
-/// [: dart pkg/test_runner/tool/co19.dart :]
-import 'package:test_runner/src/configuration.dart';
-import 'package:test_runner/src/options.dart';
-import 'package:test_runner/src/test_configurations.dart';
-
-const List<String> _commonArguments = <String>[
-  '--report',
-  '--progress=diff',
-  'co19'
-];
-
-const List<List<String>> _commandLines = <List<String>>[
-  <String>['-mrelease,debug', '-rvm', '-cnone'],
-  <String>['-mrelease,debug', '-rvm', '-cnone', '--checked'],
-  <String>['-mrelease', '-rnone', '-cdart2analyzer'],
-  <String>['-mrelease', '-rd8', '-cdart2js', '--use-sdk'],
-  <String>['-mrelease', '-rd8,jsshell', '-cdart2js', '--use-sdk', '--minified'],
-  <String>['-mrelease', '-rd8,jsshell', '-cdart2js', '--use-sdk', '--checked'],
-  <String>[
-    '-mrelease',
-    '-rd8,jsshell',
-    '-cdart2js',
-    '--use-sdk',
-    '--checked',
-    '--fast-startup'
-  ],
-];
-
-void main(List<String> args) {
-  var optionsParser = OptionsParser();
-  var configurations = <TestConfiguration>[];
-  for (var commandLine in _commandLines) {
-    var arguments = <String>[];
-    arguments.addAll(_commonArguments);
-    arguments.addAll(args);
-    arguments.addAll(commandLine);
-    configurations.addAll(optionsParser.parse(arguments));
-  }
-
-  if (configurations != null || configurations.isNotEmpty) {
-    testConfigurations(configurations);
-  }
-}
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 6c72584..3021d8e 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -23,7 +23,7 @@
 import 'dart:async' show Future, ZoneSpecification, runZoned;
 import 'dart:collection' show UnmodifiableMapBase;
 import 'dart:convert' show utf8;
-import 'dart:io' show File, Platform, stderr hide FileSystemEntity;
+import 'dart:io' show Directory, File, Platform, stderr hide FileSystemEntity;
 import 'dart:isolate';
 import 'dart:typed_data' show Uint8List;
 
@@ -535,7 +535,21 @@
   if (verbose) {
     for (int i = 0; i < request.length; i++) {
       var part = request[i];
-      String partToString = part.toString();
+      String partToString;
+      if (part is List && part.isNotEmpty) {
+        // Assume this is large and printing all of it takes a lot of time.
+        StringBuffer sb = new StringBuffer();
+        String prepend = "[";
+        for (int j = 0; j < part.length; j++) {
+          sb.write(prepend);
+          sb.write(part[j]);
+          prepend = ", ";
+          if (sb.length > 256) break;
+        }
+        partToString = sb.toString();
+      } else {
+        partToString = part.toString();
+      }
       if (partToString.length > 256) {
         partToString = partToString.substring(0, 255) + "...";
       }
@@ -683,7 +697,7 @@
     // In training mode make sure to read the sdk a few more times...
     ProcessedOptions p = new ProcessedOptions(options: compiler.options);
     var bytes = await p.loadSdkSummaryBytes();
-    for (int i = 0; i < 100; i++) {
+    for (int i = 0; i < 5; i++) {
       p.loadComponent(bytes, null);
     }
 
@@ -744,7 +758,32 @@
   return fileSystem;
 }
 
-train(String scriptUri, String platformKernelPath, bool bytecode) {
+train(String scriptUri, String platformKernelPath, bool bytecode) async {
+  // Train on program asked to train on.
+  await trainInternal(scriptUri, platformKernelPath, bytecode);
+
+  // Also train a few times on a hello-world program to make sure we exercise
+  // the startup sequence.
+  Directory tmpDir =
+      Directory.systemTemp.createTempSync("kernel_service_train");
+  File helloDart = new File.fromUri(tmpDir.uri.resolve("hello.dart"));
+  helloDart.writeAsStringSync("""
+          main() {
+            print("Hello, World!");
+          }
+          """);
+  try {
+    for (int i = 0; i < 10; i++) {
+      await trainInternal(
+          helloDart.uri.toString(), platformKernelPath, bytecode);
+    }
+  } finally {
+    tmpDir.deleteSync(recursive: true);
+  }
+}
+
+Future trainInternal(
+    String scriptUri, String platformKernelPath, bool bytecode) async {
   var tag = kTrainTag;
   var responsePort = new RawReceivePort();
   responsePort.handler = (response) {
@@ -775,7 +814,7 @@
     null /* multirootFilepaths */,
     null /* multirootScheme */,
   ];
-  _processLoadRequest(request);
+  await _processLoadRequest(request);
 }
 
 main([args]) {
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index cee493c..c14d3ab 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -1545,10 +1545,14 @@
     if (!hasErrors) {
       Code code;
       if (hasCode) {
-        if (options.emitLocalVarInfo && node.function != null) {
-          // Leave the scope which was entered in _setupInitialContext.
-          asm.localVariableTable
-              .leaveScope(asm.offset, node.function.fileEndOffset);
+        if (options.emitLocalVarInfo) {
+          // Leave the scopes which were entered in _genPrologue and
+          // _setupInitialContext.
+          asm.localVariableTable.leaveAllScopes(
+              asm.offset,
+              node.function != null
+                  ? node.function.fileEndOffset
+                  : node.fileEndOffset);
         }
 
         List<int> parameterFlags = null;
@@ -1673,47 +1677,75 @@
       asm.emitPopLocal(locals.contextVarIndexInFrame);
     }
 
-    // CheckStack must see a properly initialized context when stress-testing
-    // stack trace collection.
-    asm.emitCheckStack(0);
+    if (locals.hasFunctionTypeArgsVar && function.typeParameters.isNotEmpty) {
+      assert(!(node is Procedure && node.isFactory));
 
-    if (locals.hasFunctionTypeArgsVar) {
-      if (function.typeParameters.isNotEmpty) {
-        assert(!(node is Procedure && node.isFactory));
-
-        Label done = new Label();
-
-        if (isClosure) {
-          _handleDelayedTypeArguments(done);
-        }
-
-        asm.emitCheckFunctionTypeArgs(function.typeParameters.length,
-            locals.functionTypeArgsVarIndexInFrame);
-
-        _handleDefaultTypeArguments(function, done);
-
-        asm.bind(done);
-      }
+      Label done = new Label();
 
       if (isClosure) {
-        if (function.typeParameters.isNotEmpty) {
-          final int numParentTypeArgs = locals.numParentTypeArguments;
-          asm.emitPush(locals.functionTypeArgsVarIndexInFrame);
-          asm.emitPush(locals.closureVarIndexInFrame);
-          asm.emitLoadFieldTOS(
-              cp.addInstanceField(closureFunctionTypeArguments));
-          _genPushInt(numParentTypeArgs);
-          _genPushInt(numParentTypeArgs + function.typeParameters.length);
-          _genDirectCall(
-              prependTypeArguments, objectTable.getArgDescHandle(4), 4);
-          asm.emitPopLocal(locals.functionTypeArgsVarIndexInFrame);
-        } else {
-          asm.emitPush(locals.closureVarIndexInFrame);
-          asm.emitLoadFieldTOS(
-              cp.addInstanceField(closureFunctionTypeArguments));
-          asm.emitPopLocal(locals.functionTypeArgsVarIndexInFrame);
+        _handleDelayedTypeArguments(done);
+      }
+
+      asm.emitCheckFunctionTypeArgs(function.typeParameters.length,
+          locals.functionTypeArgsVarIndexInFrame);
+
+      _handleDefaultTypeArguments(function, done);
+
+      asm.bind(done);
+    }
+
+    // Open initial scope before the first CheckStack, as VM might
+    // need to know context level.
+    if (options.emitLocalVarInfo && function != null) {
+      asm.localVariableTable.enterScope(
+          asm.offset,
+          isClosure ? locals.contextLevelAtEntry : locals.currentContextLevel,
+          function.fileOffset);
+      if (locals.hasContextVar) {
+        asm.localVariableTable
+            .recordContextVariable(asm.offset, locals.contextVarIndexInFrame);
+      }
+      if (locals.hasReceiver) {
+        _declareLocalVariable(locals.receiverVar, function.fileOffset);
+      }
+      for (var v in function.positionalParameters) {
+        if (!locals.isCaptured(v)) {
+          _declareLocalVariable(v, function.fileOffset);
         }
       }
+      for (var v in locals.sortedNamedParameters) {
+        if (!locals.isCaptured(v)) {
+          _declareLocalVariable(v, function.fileOffset);
+        }
+      }
+      if (locals.hasFunctionTypeArgsVar) {
+        _declareLocalVariable(locals.functionTypeArgsVar, function.fileOffset);
+      }
+    }
+
+    // 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) {
+      if (function.typeParameters.isNotEmpty) {
+        final int numParentTypeArgs = locals.numParentTypeArguments;
+        asm.emitPush(locals.functionTypeArgsVarIndexInFrame);
+        asm.emitPush(locals.closureVarIndexInFrame);
+        asm.emitLoadFieldTOS(cp.addInstanceField(closureFunctionTypeArguments));
+        _genPushInt(numParentTypeArgs);
+        _genPushInt(numParentTypeArgs + function.typeParameters.length);
+        _genDirectCall(
+            prependTypeArguments, objectTable.getArgDescHandle(4), 4);
+        asm.emitPopLocal(locals.functionTypeArgsVarIndexInFrame);
+      } else {
+        asm.emitPush(locals.closureVarIndexInFrame);
+        asm.emitLoadFieldTOS(cp.addInstanceField(closureFunctionTypeArguments));
+        asm.emitPopLocal(locals.functionTypeArgsVarIndexInFrame);
+      }
     }
   }
 
@@ -1761,26 +1793,10 @@
   void _setupInitialContext(FunctionNode function) {
     _allocateContextIfNeeded();
 
-    if (options.emitLocalVarInfo && function != null) {
-      // Open scope after allocating context.
-      asm.localVariableTable.enterScope(
-          asm.offset, locals.currentContextLevel, function.fileOffset);
-      if (locals.hasContextVar) {
-        asm.localVariableTable
-            .recordContextVariable(asm.offset, locals.contextVarIndexInFrame);
-      }
-      if (locals.hasReceiver) {
-        _declareLocalVariable(locals.receiverVar, function.fileOffset);
-      }
-      for (var v in function.positionalParameters) {
-        _declareLocalVariable(v, function.fileOffset);
-      }
-      for (var v in locals.sortedNamedParameters) {
-        _declareLocalVariable(v, function.fileOffset);
-      }
-      if (locals.hasFunctionTypeArgsVar) {
-        _declareLocalVariable(locals.functionTypeArgsVar, function.fileOffset);
-      }
+    if (options.emitLocalVarInfo && locals.currentContextSize > 0) {
+      // Open a new scope after allocating context.
+      asm.localVariableTable.enterScope(asm.offset, locals.currentContextLevel,
+          function != null ? function.fileOffset : enclosingMember.fileOffset);
     }
 
     if (locals.hasCapturedParameters) {
@@ -1795,8 +1811,10 @@
           _genStoreVar(locals.capturedReceiverVar);
         }
       }
-      function.positionalParameters.forEach(_copyParamIfCaptured);
-      locals.sortedNamedParameters.forEach(_copyParamIfCaptured);
+      if (function != null) {
+        function.positionalParameters.forEach(_copyParamIfCaptured);
+        locals.sortedNamedParameters.forEach(_copyParamIfCaptured);
+      }
     }
   }
 
@@ -1825,6 +1843,9 @@
 
   void _copyParamIfCaptured(VariableDeclaration variable) {
     if (locals.isCaptured(variable)) {
+      if (options.emitLocalVarInfo) {
+        _declareLocalVariable(variable, enclosingFunction.fileOffset);
+      }
       _genPushContextForVariable(variable);
       asm.emitPush(locals.getOriginalParamSlotIndex(variable));
       _genStoreVar(variable);
@@ -2191,8 +2212,9 @@
     }
 
     if (options.emitLocalVarInfo) {
-      // Leave the scope which was entered in _setupInitialContext.
-      asm.localVariableTable.leaveScope(asm.offset, function.fileEndOffset);
+      // Leave the scopes which were entered in _genPrologue and
+      // _setupInitialContext.
+      asm.localVariableTable.leaveAllScopes(asm.offset, function.fileEndOffset);
     }
 
     cp.addEndClosureFunctionScope();
diff --git a/pkg/vm/lib/bytecode/local_variable_table.dart b/pkg/vm/lib/bytecode/local_variable_table.dart
index 9da3d17..24607fa 100644
--- a/pkg/vm/lib/bytecode/local_variable_table.dart
+++ b/pkg/vm/lib/bytecode/local_variable_table.dart
@@ -159,6 +159,12 @@
     }
   }
 
+  void leaveAllScopes(int pc, int endPosition) {
+    while (activeScopes.isNotEmpty) {
+      leaveScope(pc, endPosition);
+    }
+  }
+
   void recordContextVariable(int pc, int index) {
     assert(contextVariable == null);
     contextVariable = new ContextVariable(pc, index);
diff --git a/pkg/vm/lib/bytecode/object_table.dart b/pkg/vm/lib/bytecode/object_table.dart
index 9b35141..57452d0 100644
--- a/pkg/vm/lib/bytecode/object_table.dart
+++ b/pkg/vm/lib/bytecode/object_table.dart
@@ -6,7 +6,6 @@
 
 import 'package:kernel/ast.dart' hide MapEntry;
 import 'package:kernel/core_types.dart' show CoreTypes;
-import 'package:kernel/type_algebra.dart' show getFreshTypeParameters;
 
 import 'bytecode_serialization.dart'
     show
@@ -1962,7 +1961,7 @@
 
   @override
   ObjectHandle visitBottomType(BottomType node) =>
-      objectTable.getHandle(objectTable.coreTypes.nullClass.rawType);
+      objectTable.getHandle(objectTable.coreTypes.nullType);
 
   @override
   ObjectHandle visitInterfaceType(InterfaceType node) {
@@ -2060,27 +2059,8 @@
         .getOrAddObject(new _TypeParameterHandle(parentHandle, indexInParent));
   }
 
-  /// This is a workaround to <https://github.com/dart-lang/sdk/issues/37536>.
-  /// TODO(37536): remove this workaround once the issue is fixed.
-  ///
-  /// In certain cases, front-end produces function types with type parameters
-  /// which already belong to a closure. This results in the incorrect
-  /// canonicalization of types.
-  ///
-  /// This method corrects FunctionType by creating fresh type parameters.
-  FunctionType _fixTypeParameters(FunctionType type) {
-    for (var typeParam in type.typeParameters) {
-      if (typeParam.parent != null) {
-        final fresh = getFreshTypeParameters(type.typeParameters);
-        return fresh.applyToFunctionType(type);
-      }
-    }
-    return type;
-  }
-
   @override
   ObjectHandle visitFunctionType(FunctionType node) {
-    node = _fixTypeParameters(node);
     final int numEnclosingTypeParameters = _typeParameters.length;
     for (int i = 0; i < node.typeParameters.length; ++i) {
       _typeParameters[node.typeParameters[i]] = objectTable.getOrAddObject(
diff --git a/pkg/vm/lib/frontend_server.dart b/pkg/vm/lib/frontend_server.dart
index ba383ba..65164f6 100644
--- a/pkg/vm/lib/frontend_server.dart
+++ b/pkg/vm/lib/frontend_server.dart
@@ -361,6 +361,7 @@
     }
 
     Component component;
+    Iterable<Uri> compiledSources;
     if (options['incremental']) {
       _compilerOptions = compilerOptions;
       _bytecodeOptions = bytecodeOptions;
@@ -370,8 +371,11 @@
       _generator =
           generator ?? _createGenerator(new Uri.file(_initializeFromDill));
       await invalidateIfInitializingFromDill();
-      component = await _runWithPrintRedirection(() async =>
-          await _generateBytecodeIfNeeded(await _generator.compile()));
+      component = await _runWithPrintRedirection(() async {
+        final c = await _generator.compile();
+        compiledSources = c.uriToSource.keys;
+        return await _generateBytecodeIfNeeded(c);
+      });
     } else {
       if (options['link-platform']) {
         // TODO(aam): Remove linkedDependencies once platform is directly embedded
@@ -380,7 +384,7 @@
           sdkRoot.resolve(platformKernelDill)
         ];
       }
-      component = await _runWithPrintRedirection(() => compileToKernel(
+      final results = await _runWithPrintRedirection(() => compileToKernel(
           _mainSource, compilerOptions,
           aot: options['aot'],
           useGlobalTypeFlowAnalysis: options['tfa'],
@@ -389,6 +393,8 @@
           bytecodeOptions: bytecodeOptions,
           dropAST: options['drop-ast'],
           useProtobufTreeShaker: options['protobuf-tree-shaker']));
+      component = results.component;
+      compiledSources = results.compiledSources;
     }
     if (component != null) {
       if (transformer != null) {
@@ -399,12 +405,12 @@
           filterExternal: importDill != null);
 
       _outputStream.writeln(boundaryKey);
-      await _outputDependenciesDelta(component);
+      await _outputDependenciesDelta(compiledSources);
       _outputStream
           .writeln('$boundaryKey $_kernelBinaryFilename ${errors.length}');
       final String depfile = options['depfile'];
       if (depfile != null) {
-        await writeDepfile(compilerOptions.fileSystem, component,
+        await writeDepfile(compilerOptions.fileSystem, compiledSources,
             _kernelBinaryFilename, depfile);
       }
 
@@ -430,9 +436,9 @@
     return component;
   }
 
-  void _outputDependenciesDelta(Component component) async {
+  void _outputDependenciesDelta(Iterable<Uri> compiledSources) async {
     Set<Uri> uris = new Set<Uri>();
-    for (Uri uri in component.uriToSource.keys) {
+    for (Uri uri in compiledSources) {
       // Skip empty or corelib dependencies.
       if (uri == null || uri.scheme == 'org-dartlang-sdk') continue;
       uris.add(uri);
@@ -557,10 +563,11 @@
     if (deltaProgram != null && transformer != null) {
       transformer.transform(deltaProgram);
     }
+    final compiledSources = deltaProgram.uriToSource.keys;
     deltaProgram = await _generateBytecodeIfNeeded(deltaProgram);
     await writeDillFile(deltaProgram, _kernelBinaryFilename);
     _outputStream.writeln(boundaryKey);
-    await _outputDependenciesDelta(deltaProgram);
+    await _outputDependenciesDelta(compiledSources);
     _outputStream
         .writeln('$boundaryKey $_kernelBinaryFilename ${errors.length}');
     _kernelBinaryFilename = _kernelBinaryFilenameIncremental;
@@ -902,6 +909,11 @@
   }
 
   if (options['train']) {
+    if (options.rest.isEmpty) {
+      throw Exception('Must specify input.dart');
+    }
+
+    final String input = options.rest[0];
     final String sdkRoot = options['sdk-root'];
     final String platform = options['platform'];
     final Directory temp =
@@ -920,8 +932,7 @@
       compiler ??=
           new FrontendCompiler(output, printerFactory: binaryPrinterFactory);
 
-      await compiler.compile(Platform.script.toFilePath(), options,
-          generator: generator);
+      await compiler.compile(input, options, generator: generator);
       compiler.acceptLastDelta();
       await compiler.recompileDelta();
       compiler.acceptLastDelta();
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 49262b7..3c71ea3 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -212,7 +212,7 @@
     }
     ..embedSourceText = embedSources;
 
-  final component = await compileToKernel(mainUri, compilerOptions,
+  final results = await compileToKernel(mainUri, compilerOptions,
       aot: aot,
       useGlobalTypeFlowAnalysis: tfa,
       environmentDefines: environmentDefines,
@@ -223,7 +223,7 @@
 
   errorPrinter.printCompilationMessages();
 
-  if (errorDetector.hasCompilationErrors || (component == null)) {
+  if (errorDetector.hasCompilationErrors || (results.component == null)) {
     return compileTimeErrorExitCode;
   }
 
@@ -233,7 +233,7 @@
 
   final IOSink sink = new File(outputFileName).openWrite();
   final BinaryPrinter printer = new BinaryPrinter(sink);
-  printer.writeComponentFile(component);
+  printer.writeComponentFile(results.component);
   await sink.close();
 
   if (bytecodeOptions.showBytecodeSizeStatistics && !splitOutputByPackages) {
@@ -241,14 +241,15 @@
   }
 
   if (depfile != null) {
-    await writeDepfile(fileSystem, component, outputFileName, depfile);
+    await writeDepfile(
+        fileSystem, results.compiledSources, outputFileName, depfile);
   }
 
   if (splitOutputByPackages) {
     await writeOutputSplitByPackages(
       mainUri,
       compilerOptions,
-      component,
+      results.component,
       outputFileName,
       genBytecode: genBytecode,
       bytecodeOptions: bytecodeOptions,
@@ -259,12 +260,22 @@
   return successExitCode;
 }
 
+/// Results of [compileToKernel]: generated kernel [Component] and
+/// collection of compiled sources.
+class KernelCompilationResults {
+  final Component component;
+  final Iterable<Uri> compiledSources;
+
+  KernelCompilationResults(this.component, this.compiledSources);
+}
+
 /// Generates a kernel representation of the program whose main library is in
 /// the given [source]. Intended for whole program (non-modular) compilation.
 ///
 /// VM-specific replacement of [kernelForProgram].
 ///
-Future<Component> compileToKernel(Uri source, CompilerOptions options,
+Future<KernelCompilationResults> compileToKernel(
+    Uri source, CompilerOptions options,
     {bool aot: false,
     bool useGlobalTypeFlowAnalysis: false,
     Map<String, String> environmentDefines,
@@ -280,6 +291,7 @@
   setVMEnvironmentDefines(environmentDefines, options);
   CompilerResult compilerResult = await kernelForProgram(source, options);
   Component component = compilerResult?.component;
+  final compiledSources = component?.uriToSource?.keys;
 
   // Run global transformations only if component is correct.
   if (aot && component != null) {
@@ -306,7 +318,7 @@
   // Restore error handler (in case 'options' are reused).
   options.onDiagnostic = errorDetector.previousErrorHandler;
 
-  return component;
+  return new KernelCompilationResults(component, compiledSources);
 }
 
 void setVMEnvironmentDefines(
@@ -686,12 +698,12 @@
 
 /// Create ninja dependencies file, as described in
 /// https://ninja-build.org/manual.html#_depfile
-Future<void> writeDepfile(FileSystem fileSystem, Component component,
+Future<void> writeDepfile(FileSystem fileSystem, Iterable<Uri> compiledSources,
     String output, String depfile) async {
   final IOSink file = new File(depfile).openWrite();
   file.write(_escapePath(output));
   file.write(':');
-  for (Uri dep in component.uriToSource.keys) {
+  for (Uri dep in compiledSources) {
     // Skip empty or corelib dependencies.
     if (dep == null || dep.scheme == 'org-dartlang-sdk') continue;
     Uri uri = await asFileUri(fileSystem, dep);
diff --git a/pkg/vm/lib/target/dart_runner.dart b/pkg/vm/lib/target/dart_runner.dart
index 270f365..fc814ac 100644
--- a/pkg/vm/lib/target/dart_runner.dart
+++ b/pkg/vm/lib/target/dart_runner.dart
@@ -45,7 +45,5 @@
       ];
 
   @override
-  List<String> get extraRequiredLibrariesPlatform => const <String>[
-        'dart:profiler',
-      ];
+  List<String> get extraRequiredLibrariesPlatform => const <String>[];
 }
diff --git a/pkg/vm/lib/target/flutter.dart b/pkg/vm/lib/target/flutter.dart
index 8022a27..9d63c74 100644
--- a/pkg/vm/lib/target/flutter.dart
+++ b/pkg/vm/lib/target/flutter.dart
@@ -48,9 +48,7 @@
       ];
 
   @override
-  List<String> get extraRequiredLibrariesPlatform => const <String>[
-        'dart:profiler',
-      ];
+  List<String> get extraRequiredLibrariesPlatform => const <String>[];
 
   @override
   void performPreConstantEvaluationTransformations(
diff --git a/pkg/vm/lib/target/flutter_runner.dart b/pkg/vm/lib/target/flutter_runner.dart
index 53363e2..816c030 100644
--- a/pkg/vm/lib/target/flutter_runner.dart
+++ b/pkg/vm/lib/target/flutter_runner.dart
@@ -46,7 +46,5 @@
       ];
 
   @override
-  List<String> get extraRequiredLibrariesPlatform => const <String>[
-        'dart:profiler',
-      ];
+  List<String> get extraRequiredLibrariesPlatform => const <String>[];
 }
diff --git a/pkg/vm/lib/target/vm.dart b/pkg/vm/lib/target/vm.dart
index 23a6832..eefc73c 100644
--- a/pkg/vm/lib/target/vm.dart
+++ b/pkg/vm/lib/target/vm.dart
@@ -41,9 +41,6 @@
   VmTarget(this.flags);
 
   @override
-  bool get legacyMode => flags.legacyMode;
-
-  @override
   bool get enableNoSuchMethodForwarders => true;
 
   @override
@@ -80,9 +77,7 @@
       ];
 
   @override
-  List<String> get extraRequiredLibrariesPlatform => const <String>[
-        'dart:profiler',
-      ];
+  List<String> get extraRequiredLibrariesPlatform => const <String>[];
 
   void _patchVmConstants(CoreTypes coreTypes) {
     // Fix Endian.host to be a const field equal to Endian.little instead of
@@ -181,7 +176,7 @@
           new IntLiteral(type)..fileOffset = offset,
           _fixedLengthList(
               coreTypes,
-              coreTypes.typeClass.rawType,
+              coreTypes.typeLegacyRawType,
               arguments.types.map((t) => new TypeLiteral(t)).toList(),
               arguments.fileOffset),
           _fixedLengthList(coreTypes, const DynamicType(), arguments.positional,
@@ -195,11 +190,11 @@
                       new SymbolLiteral(arg.name)..fileOffset = arg.fileOffset,
                       arg.value)
                     ..fileOffset = arg.fileOffset;
-                })), keyType: coreTypes.symbolClass.rawType)
+                })), keyType: coreTypes.symbolLegacyRawType)
                   ..isConst = (arguments.named.length == 0)
                   ..fileOffset = arguments.fileOffset
               ], types: [
-                coreTypes.symbolClass.rawType,
+                coreTypes.symbolLegacyRawType,
                 new DynamicType()
               ]))
             ..fileOffset = offset
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index 2d434d2..75a8332 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -134,7 +134,7 @@
     final nsmArgs = new Args<Type>([
       receiver,
       new Type.cone(
-          typeFlowAnalysis.environment.coreTypes.invocationClass.rawType)
+          typeFlowAnalysis.environment.coreTypes.invocationLegacyRawType)
     ]);
 
     final nsmInvocation =
@@ -438,8 +438,9 @@
     }
 
     if (selector is InterfaceSelector) {
-      final staticReceiverType =
-          new Type.fromStatic(selector.member.enclosingClass.rawType);
+      final staticReceiverType = new Type.fromStatic(typeFlowAnalysis
+          .environment.coreTypes
+          .legacyRawType(selector.member.enclosingClass));
       receiver = receiver.intersection(
           staticReceiverType, typeFlowAnalysis.hierarchyCache);
       assertx(receiver is! NullableType);
@@ -1239,6 +1240,7 @@
   Class get futureOrClass => environment.coreTypes.futureOrClass;
   Class get futureClass => environment.coreTypes.futureClass;
   Class get functionClass => environment.coreTypes.functionClass;
+  CoreTypes get coreTypes => environment.coreTypes;
 }
 
 class _WorkList {
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index 7254e6c..a5d3532 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -344,8 +344,8 @@
         _summary = new Summary(
             parameterCount: numArgs, positionalParameterCount: numArgs);
         // TODO(alexmarkov): subclass cone
-        _receiver = _declareParameter(
-            "this", member.enclosingClass.rawType, null,
+        _receiver = _declareParameter("this",
+            _environment.coreTypes.legacyRawType(member.enclosingClass), null,
             isReceiver: true);
         _environment.thisType = member.enclosingClass?.thisType;
       } else {
@@ -391,8 +391,8 @@
 
       if (hasReceiver) {
         // TODO(alexmarkov): subclass cone
-        _receiver = _declareParameter(
-            "this", member.enclosingClass.rawType, null,
+        _receiver = _declareParameter("this",
+            _environment.coreTypes.legacyRawType(member.enclosingClass), null,
             isReceiver: true);
         _environment.thisType = member.enclosingClass?.thisType;
       }
@@ -524,7 +524,8 @@
 
     if (hasReceiverArg(member)) {
       assertx(member.enclosingClass != null);
-      Type receiver = new Type.cone(member.enclosingClass.rawType);
+      Type receiver = new Type.cone(
+          _environment.coreTypes.legacyRawType(member.enclosingClass));
       args.add(receiver);
     }
 
diff --git a/pkg/vm/lib/transformations/type_flow/types.dart b/pkg/vm/lib/transformations/type_flow/types.dart
index 9d34b39..4b5a7a1 100644
--- a/pkg/vm/lib/transformations/type_flow/types.dart
+++ b/pkg/vm/lib/transformations/type_flow/types.dart
@@ -9,6 +9,8 @@
 
 import 'package:kernel/ast.dart';
 
+import 'package:kernel/core_types.dart';
+
 import 'utils.dart';
 
 abstract class GenericInterfacesInfo {
@@ -46,6 +48,7 @@
   Class get futureOrClass;
   Class get futureClass;
   Class get functionClass;
+  CoreTypes get coreTypes;
 }
 
 /// Basic normalization of Dart types.
@@ -53,7 +56,12 @@
 DartType _normalizeDartType(DartType type) {
   if (type is InterfaceType) {
     // TODO(alexmarkov): take generic type arguments into account
-    return type.classNode.rawType;
+    // TODO(alexmarkov): cache the created raw type or use a CoreTypes object
+    return new InterfaceType(
+        type.classNode,
+        new List<DartType>.filled(
+            type.classNode.typeParameters.length, const DynamicType()),
+        Nullability.legacy);
   } else if (type is FunctionType) {
     // TODO(alexmarkov): support function types
     return const DynamicType();
@@ -536,7 +544,9 @@
         return other;
       }
     } else if (other is ConcreteType) {
-      if (typeHierarchy.isSubtype(other.classNode.rawType, this.dartType)) {
+      if (typeHierarchy.isSubtype(
+          typeHierarchy.coreTypes.legacyRawType(other.classNode),
+          this.dartType)) {
         return this;
       }
     }
@@ -561,7 +571,9 @@
         return this;
       }
     } else if (other is ConcreteType) {
-      if (typeHierarchy.isSubtype(other.classNode.rawType, this.dartType)) {
+      if (typeHierarchy.isSubtype(
+          typeHierarchy.coreTypes.legacyRawType(other.classNode),
+          this.dartType)) {
         return other;
       } else {
         return const EmptyType();
@@ -626,7 +638,8 @@
 
   @override
   bool isSubtypeOf(TypeHierarchy typeHierarchy, DartType dartType) =>
-      typeHierarchy.isSubtype(classNode.rawType, dartType);
+      typeHierarchy.isSubtype(
+          typeHierarchy.coreTypes.legacyRawType(classNode), dartType);
 
   bool isSubtypeOfRuntimeType(
       TypeHierarchy typeHierarchy, RuntimeType runtimeType) {
@@ -639,7 +652,9 @@
       return false;
     }
 
-    if (!typeHierarchy.isSubtype(this.classNode.rawType, runtimeType._type)) {
+    if (!typeHierarchy.isSubtype(
+        typeHierarchy.coreTypes.legacyRawType(this.classNode),
+        runtimeType._type)) {
       return false;
     }
 
@@ -649,7 +664,8 @@
       if (runtimeDartType.typeArguments.isEmpty) return true;
       if (runtimeDartType.classNode == typeHierarchy.futureOrClass) {
         if (typeHierarchy.isSubtype(
-                classNode.rawType, typeHierarchy.futureClass.rawType) ||
+                typeHierarchy.coreTypes.legacyRawType(classNode),
+                typeHierarchy.coreTypes.futureLegacyRawType) ||
             classNode == typeHierarchy.futureOrClass) {
           final RuntimeType lhs =
               typeArgs == null ? RuntimeType(DynamicType(), null) : typeArgs[0];
diff --git a/pkg/vm/test/frontend_server_test.dart b/pkg/vm/test/frontend_server_test.dart
index ed121c0..37df317 100644
--- a/pkg/vm/test/frontend_server_test.dart
+++ b/pkg/vm/test/frontend_server_test.dart
@@ -28,7 +28,7 @@
     final CompilerInterface compiler = new _MockedCompiler();
 
     test('train with mocked compiler completes', () async {
-      await starter(<String>['--train'], compiler: compiler);
+      await starter(<String>['--train', 'foo.dart'], compiler: compiler);
     });
   });
 
@@ -313,6 +313,14 @@
       '--incremental',
     ];
 
+    Directory tempDir;
+    setUp(() {
+      tempDir = Directory.systemTemp.createTempSync();
+    });
+    tearDown(() {
+      tempDir.delete(recursive: true);
+    });
+
     test('compile then accept', () async {
       final StreamController<List<int>> inputStreamController =
           new StreamController<List<int>>();
@@ -359,11 +367,13 @@
         binaryPrinterFactory: printerFactory,
       );
 
-      inputStreamController.add('compile file1.dart\n'.codeUnits);
+      final source = new File('${tempDir.path}/file1.dart');
+      inputStreamController.add('compile ${source.path}\n'.codeUnits);
       await receivedResult.first;
       inputStreamController.add('accept\n'.codeUnits);
       receivedResult = new ReceivePort();
-      inputStreamController.add('recompile def\nfile1.dart\ndef\n'.codeUnits);
+      inputStreamController
+          .add('recompile def\n${source.path}\ndef\n'.codeUnits);
       await receivedResult.first;
 
       inputStreamController.add('quit\n'.codeUnits);
@@ -989,11 +999,41 @@
         '--platform=${platformKernel.path}',
         '--output-dill=${dillFile.path}',
         '--gen-bytecode',
+        '--drop-ast',
         file.path,
       ];
       expect(await starter(args), 0);
     });
 
+    test('compile with bytecode and produce deps file', () async {
+      var sourceFoo = new File('${tempDir.path}/foo.dart')..createSync();
+      sourceFoo.writeAsStringSync("import 'bar.dart'; main() { barfunc(); }\n");
+      var sourceBar = new File('${tempDir.path}/bar.dart')..createSync();
+      sourceBar.writeAsStringSync("barfunc() {}\n");
+      var dillFile = new File('${tempDir.path}/app.dill');
+      expect(dillFile.existsSync(), equals(false));
+      var depFile = new File('${tempDir.path}/app.dill.d');
+      expect(depFile.existsSync(), equals(false));
+      final List<String> args = <String>[
+        '--sdk-root=${sdkRoot.toFilePath()}',
+        '--incremental',
+        '--platform=${platformKernel.path}',
+        '--output-dill=${dillFile.path}',
+        '--depfile=${depFile.path}',
+        '--gen-bytecode',
+        '--drop-ast',
+        sourceFoo.path,
+      ];
+      expect(await starter(args), 0);
+      expect(depFile.existsSync(), true);
+      var depContents = depFile.readAsStringSync();
+      print(depContents);
+      var depContentsParsed = depContents.split(': ');
+      expect(path.basename(depContentsParsed[0]), path.basename(dillFile.path));
+      expect(depContentsParsed[1], contains(path.basename(sourceFoo.path)));
+      expect(depContentsParsed[1], contains(path.basename(sourceBar.path)));
+    });
+
     test('compile "package:"-file', () async {
       Directory lib = new Directory('${tempDir.path}/lib')..createSync();
       new File('${lib.path}/foo.dart')
diff --git a/pkg/vm/test/transformations/type_flow/types_test.dart b/pkg/vm/test/transformations/type_flow/types_test.dart
index b317843..3d2dc5d 100644
--- a/pkg/vm/test/transformations/type_flow/types_test.dart
+++ b/pkg/vm/test/transformations/type_flow/types_test.dart
@@ -5,12 +5,14 @@
 import 'dart:core' hide Type;
 
 import 'package:kernel/ast.dart';
+import 'package:kernel/core_types.dart';
 import 'package:test/test.dart';
 import 'package:vm/transformations/type_flow/types.dart';
 
 class TestTypeHierarchy implements TypeHierarchy {
   final Map<DartType, List<DartType>> subtypes;
   final Map<DartType, Type> specializations;
+  final CoreTypes coreTypes = new CoreTypes(new Component());
 
   TestTypeHierarchy(this.subtypes, this.specializations);
 
diff --git a/pkg/vm/testcases/bytecode/async.dart.expect b/pkg/vm/testcases/bytecode/async.dart.expect
index 74730b1..e79ab6e 100644
--- a/pkg/vm/testcases/bytecode/async.dart.expect
+++ b/pkg/vm/testcases/bytecode/async.dart.expect
@@ -2207,9 +2207,9 @@
 
   import "dart:async";
 
-  static field (dart.async::Future<dart.core::int*>*) →* dart.async::Future<dart.core::Null*>* asyncInFieldInitializer = (dart.async::Future<dart.core::int*>* x) → dart.async::Future<dart.core::Null*>* /* originally async */ {
-    final dart.async::_AsyncAwaitCompleter<dart.core::Null*>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dart.core::Null*>();
-    dart.async::FutureOr<dart.core::Null*>* :return_value;
+  static field (dart.async::Future<dart.core::int*>*) →* dart.async::Future<dart.core::Null?>* asyncInFieldInitializer = (dart.async::Future<dart.core::int*>* x) → dart.async::Future<dart.core::Null?>* /* originally async */ {
+    final dart.async::_AsyncAwaitCompleter<dart.core::Null?>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dart.core::Null?>();
+    dart.async::FutureOr<dart.core::Null?>* :return_value;
     dynamic :async_stack_trace;
     dynamic :async_op_then;
     dynamic :async_op_error;
diff --git a/pkg/vm/testcases/bytecode/closures.dart.expect b/pkg/vm/testcases/bytecode/closures.dart.expect
index 76d15ca..3b9cc78 100644
--- a/pkg/vm/testcases/bytecode/closures.dart.expect
+++ b/pkg/vm/testcases/bytecode/closures.dart.expect
@@ -103,8 +103,8 @@
 
 Bytecode {
   Entry                2
-  CheckStack           0
   CheckFunctionTypeArgs 8, r0
+  CheckStack           0
   PushConstant         CP#0
   StoreLocal           r1
   Push                 r1
@@ -321,7 +321,6 @@
   Push                 FP[-6]
   LoadFieldTOS         CP#1
   PopLocal             r1
-  CheckStack           0
   Push                 FP[-6]
   LoadFieldTOS         CP#3
   StoreLocal           r0
@@ -332,6 +331,7 @@
 L1:
   CheckFunctionTypeArgs 1, r0
 L2:
+  CheckStack           0
   Push                 r0
   Push                 FP[-6]
   LoadFieldTOS         CP#6
@@ -573,8 +573,8 @@
 
 Bytecode {
   Entry                5
-  CheckStack           0
   CheckFunctionTypeArgs 2, r0
+  CheckStack           0
   AllocateContext      0, 1
   PopLocal             r1
   Push                 r1
@@ -664,7 +664,6 @@
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r1
-  CheckStack           0
   Push                 FP[-5]
   LoadFieldTOS         CP#3
   StoreLocal           r0
@@ -675,6 +674,7 @@
 L1:
   CheckFunctionTypeArgs 2, r0
 L2:
+  CheckStack           0
   Push                 r0
   Push                 FP[-5]
   LoadFieldTOS         CP#6
@@ -724,7 +724,6 @@
   Push                 FP[-5]
   LoadFieldTOS         CP#1
   PopLocal             r1
-  CheckStack           0
   Push                 FP[-5]
   LoadFieldTOS         CP#3
   StoreLocal           r0
@@ -735,6 +734,7 @@
 L1:
   CheckFunctionTypeArgs 2, r0
 L2:
+  CheckStack           0
   Push                 r0
   Push                 FP[-5]
   LoadFieldTOS         CP#6
@@ -1656,11 +1656,11 @@
     method foo<T3 extends dart.core::Object* = dynamic, T4 extends dart.core::Object* = dynamic>() → void {
       function nested1<T5 extends dart.core::Object* = dynamic, T6 extends dart.core::Object* = dynamic>() → void {
         function nested2<T7 extends dart.core::Object* = dynamic, T8 extends dart.core::Object* = dynamic>() → void {
-          () →* dart.core::Null* nested3 = () → dart.core::Null* {
+          () →* dart.core::Null? nested3 = () → dart.core::Null? {
             dart.core::print(<dart.core::Type*>[#lib::A::T1*, #lib::A::T2*, #lib::A::foo::T3*, #lib::A::foo::T4*, T5*, T6*, T7*, T8*]);
             #lib::callWithArgs<#lib::A::T1*, #lib::A::T2*, #lib::A::foo::T3*, #lib::A::foo::T4*, T5*, T6*, T7*, T8*>();
           };
-          [@vm.call-site-attributes.metadata=receiverType:() →* dart.core::Null*] nested3.call();
+          [@vm.call-site-attributes.metadata=receiverType:() →* dart.core::Null?] nested3.call();
         }
         [@vm.call-site-attributes.metadata=receiverType:<T7 extends dart.core::Object* = dynamic, T8 extends dart.core::Object* = dynamic>() →* void] nested2.call<#lib::C7*, #lib::C8*>();
         [@vm.call-site-attributes.metadata=receiverType:<T7 extends dart.core::Object* = dynamic, T8 extends dart.core::Object* = dynamic>() →* void] nested2.call<dart.core::List<#lib::C7*>*, dart.core::List<#lib::C8*>*>();
@@ -1680,7 +1680,7 @@
         {
           dart.core::int* y = 2;
           dart.core::int* z = 3;
-          (dart.core::int*) →* dart.core::Null* closure1 = (dart.core::int* y) → dart.core::Null* {
+          (dart.core::int*) →* dart.core::Null? closure1 = (dart.core::int* y) → dart.core::Null? {
             x = y.{dart.core::num::+}(1);
             if(x.{dart.core::num::>}(5)) {
               dart.core::int* w = 4;
@@ -1692,8 +1692,8 @@
               dart.core::print(w);
             }
           };
-          [@vm.call-site-attributes.metadata=receiverType:(dart.core::int*) →* dart.core::Null*] closure1.call(10);
-          [@vm.call-site-attributes.metadata=receiverType:(dart.core::int*) →* dart.core::Null*] closure1.call(11);
+          [@vm.call-site-attributes.metadata=receiverType:(dart.core::int*) →* dart.core::Null?] closure1.call(10);
+          [@vm.call-site-attributes.metadata=receiverType:(dart.core::int*) →* dart.core::Null?] closure1.call(11);
           dart.core::print(y);
           dart.core::print(z);
         }
@@ -1701,10 +1701,10 @@
       }
       {
         dart.core::int* x = 42;
-        () →* dart.core::Null* closure3 = () → dart.core::Null* {
+        () →* dart.core::Null? closure3 = () → dart.core::Null? {
           this.{#lib::B::foo} = x;
         };
-        [@vm.call-site-attributes.metadata=receiverType:() →* dart.core::Null*] closure3.call();
+        [@vm.call-site-attributes.metadata=receiverType:() →* dart.core::Null?] closure3.call();
       }
     }
   }
@@ -1718,17 +1718,17 @@
       dart.core::List<dart.core::Function*>* setI = <dart.core::Function*>[];
       for (dart.core::int* i = 0; i.{dart.core::num::<}(10); i = i.{dart.core::num::+}(1)) {
         [@vm.call-site-attributes.metadata=receiverType:dart.core::List<dart.core::Function*>*] getI.{dart.core::List::add}(() → dart.core::int* => i.{dart.core::num::+}(delta));
-        [@vm.call-site-attributes.metadata=receiverType:dart.core::List<dart.core::Function*>*] setI.{dart.core::List::add}((dart.core::int* ii) → dart.core::Null* {
+        [@vm.call-site-attributes.metadata=receiverType:dart.core::List<dart.core::Function*>*] setI.{dart.core::List::add}((dart.core::int* ii) → dart.core::Null? {
           i = ii.{dart.core::num::+}(delta);
         });
       }
     }
     method testForInLoop(dart.core::List<dart.core::int*>* list) → void {
       for (dart.core::int* i in list) {
-        () →* dart.core::Null* inc = () → dart.core::Null* {
+        () →* dart.core::Null? inc = () → dart.core::Null? {
           i = i.{dart.core::num::+}(1);
         };
-        [@vm.call-site-attributes.metadata=receiverType:() →* dart.core::Null*] inc.call();
+        [@vm.call-site-attributes.metadata=receiverType:() →* dart.core::Null?] inc.call();
         dart.core::print(i);
       }
     }
@@ -1741,18 +1741,18 @@
       return () → #lib::D::T* => t;
     }
     method bar() → dynamic {
-      return () → dart.core::Null* {
-        function inner() → dart.core::Null* {}
-        [@vm.call-site-attributes.metadata=receiverType:() →* dart.core::Null*] inner.call();
+      return () → dart.core::Null? {
+        function inner() → dart.core::Null? {}
+        [@vm.call-site-attributes.metadata=receiverType:() →* dart.core::Null?] inner.call();
       };
     }
   }
   static method simpleClosure() → dart.core::int* {
     dart.core::int* x = 5;
-    (dart.core::int*) →* dart.core::Null* inc = (dart.core::int* y) → dart.core::Null* {
+    (dart.core::int*) →* dart.core::Null? inc = (dart.core::int* y) → dart.core::Null? {
       x = x.{dart.core::num::+}(y);
     };
-    [@vm.call-site-attributes.metadata=receiverType:(dart.core::int*) →* dart.core::Null*] inc.call(3);
+    [@vm.call-site-attributes.metadata=receiverType:(dart.core::int*) →* dart.core::Null?] inc.call(3);
     return x;
   }
   static method callWithArgs<T1 extends dart.core::Object* = dynamic, T2 extends dart.core::Object* = dynamic, T3 extends dart.core::Object* = dynamic, T4 extends dart.core::Object* = dynamic, T5 extends dart.core::Object* = dynamic, T6 extends dart.core::Object* = dynamic, T7 extends dart.core::Object* = dynamic, T8 extends dart.core::Object* = dynamic>() → void {
diff --git a/pkg/vm/testcases/bytecode/instance_creation.dart.expect b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
index 3154298..cb085fd 100644
--- a/pkg/vm/testcases/bytecode/instance_creation.dart.expect
+++ b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
@@ -80,8 +80,8 @@
 
 Bytecode {
   Entry                2
-  CheckStack           0
   CheckFunctionTypeArgs 1, r0
+  CheckStack           0
   PushNull
   Push                 r0
   InstantiateTypeArgumentsTOS 0, CP#1
diff --git a/pkg/vm/testcases/bytecode/literals.dart.expect b/pkg/vm/testcases/bytecode/literals.dart.expect
index 5b63921..b698f7ce 100644
--- a/pkg/vm/testcases/bytecode/literals.dart.expect
+++ b/pkg/vm/testcases/bytecode/literals.dart.expect
@@ -205,8 +205,8 @@
 
 Bytecode {
   Entry                2
-  CheckStack           0
   CheckFunctionTypeArgs 1, r0
+  CheckStack           0
   PushConstant         CP#0
   PushConstant         CP#1
   PushInt              4
@@ -332,8 +332,8 @@
 
 Bytecode {
   Entry                1
-  CheckStack           0
   CheckFunctionTypeArgs 1, r0
+  CheckStack           0
   PushConstant         CP#0
   DirectCall           CP#1, 1
   Drop1
diff --git a/pkg/vm/testcases/bytecode/optional_params.dart.expect b/pkg/vm/testcases/bytecode/optional_params.dart.expect
index 035d76c1..09d42e2 100644
--- a/pkg/vm/testcases/bytecode/optional_params.dart.expect
+++ b/pkg/vm/testcases/bytecode/optional_params.dart.expect
@@ -204,8 +204,8 @@
   LoadConstant         r3, CP#2
   LoadConstant         r3, CP#3
   Frame                1
-  CheckStack           0
   CheckFunctionTypeArgs 2, r4
+  CheckStack           0
   PushNull
   Push                 r4
   InstantiateType      CP#4
diff --git a/pkg/vm/testcases/bytecode/super_calls.dart.expect b/pkg/vm/testcases/bytecode/super_calls.dart.expect
index aabc371..32781bb 100644
--- a/pkg/vm/testcases/bytecode/super_calls.dart.expect
+++ b/pkg/vm/testcases/bytecode/super_calls.dart.expect
@@ -53,8 +53,8 @@
 
 Bytecode {
   Entry                1
-  CheckStack           0
   CheckFunctionTypeArgs 1, r0
+  CheckStack           0
   PushNull
   ReturnTOS
 }
diff --git a/pkg/vm/testcases/bytecode/type_ops.dart.expect b/pkg/vm/testcases/bytecode/type_ops.dart.expect
index af14940..de2ecc3 100644
--- a/pkg/vm/testcases/bytecode/type_ops.dart.expect
+++ b/pkg/vm/testcases/bytecode/type_ops.dart.expect
@@ -276,8 +276,8 @@
 
 Bytecode {
   Entry                1
-  CheckStack           0
   CheckFunctionTypeArgs 2, r0
+  CheckStack           0
   Push                 FP[-5]
   PushNull
   Push                 r0
@@ -402,7 +402,6 @@
 
 Bytecode {
   Entry                1
-  CheckStack           0
   CheckFunctionTypeArgs 2, r0
   JumpIfNotZeroTypeArgs L1
   Push                 FP[-6]
@@ -411,6 +410,7 @@
   InstantiateTypeArgumentsTOS 0, CP#1
   PopLocal             r0
 L1:
+  CheckStack           0
   JumpIfUnchecked      L2
   Push                 FP[-6]
   LoadTypeArgumentsField CP#0
@@ -496,13 +496,13 @@
 
 Bytecode {
   Entry                1
-  CheckStack           0
   CheckFunctionTypeArgs 1, r0
   JumpIfNotZeroTypeArgs L1
   Push                 FP[-8]
   LoadTypeArgumentsField CP#0
   PopLocal             r0
 L1:
+  CheckStack           0
   JumpIfUnchecked      L2
   Push                 FP[-8]
   LoadTypeArgumentsField CP#0
@@ -567,13 +567,13 @@
 
 Bytecode {
   Entry                1
-  CheckStack           0
   CheckFunctionTypeArgs 1, r0
   JumpIfNotZeroTypeArgs L1
   Push                 FP[-8]
   LoadTypeArgumentsField CP#0
   PopLocal             r0
 L1:
+  CheckStack           0
   JumpIfUnchecked      L2
   Push                 FP[-8]
   LoadTypeArgumentsField CP#0
@@ -614,8 +614,8 @@
 
 Bytecode {
   Entry                2
-  CheckStack           0
   CheckFunctionTypeArgs 1, r0
+  CheckStack           0
   JumpIfUnchecked      L1
   Push                 FP[-8]
   LoadTypeArgumentsField CP#0
diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md
index cd25650..68ded73 100644
--- a/pkg/vm_service/CHANGELOG.md
+++ b/pkg/vm_service/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Changelog
 
+## 2.0.0
+- **breaking**: VM service objects which have fields now have constructors with
+  named parameters for each field. Required fields are annotated with `@required`.
+
 ## 1.2.0
 - Support service protocol version 3.27:
   - Added `getCpuSamples` and `clearCpuSamples` methods
diff --git a/pkg/vm_service/java/src/org/dartlang/vm/service/VmServiceBase.java b/pkg/vm_service/java/src/org/dartlang/vm/service/VmServiceBase.java
index f794f6f..f335d5c 100644
--- a/pkg/vm_service/java/src/org/dartlang/vm/service/VmServiceBase.java
+++ b/pkg/vm_service/java/src/org/dartlang/vm/service/VmServiceBase.java
@@ -618,11 +618,13 @@
         Logging.getLogger().logError("Response has invalid " + RESULT, e);
         return;
       }
-      String responseType;
-      try {
+      String responseType = "";
+      if (result.has(TYPE)) {
         responseType = result.get(TYPE).getAsString();
-      } catch (Exception e) {
-        Logging.getLogger().logError("Response missing " + TYPE, e);
+      }
+      // ServiceExtensionConsumers do not care about the response type.
+      else if (!(consumer instanceof ServiceExtensionConsumer)) {
+        Logging.getLogger().logError("Response missing " + TYPE + ": " + result.toString());
         return;
       }
       forwardResponse(consumer, responseType, result);
diff --git a/pkg/vm_service/lib/src/service_extension_registry.dart b/pkg/vm_service/lib/src/service_extension_registry.dart
index e256466..9ec1514 100644
--- a/pkg/vm_service/lib/src/service_extension_registry.dart
+++ b/pkg/vm_service/lib/src/service_extension_registry.dart
@@ -60,8 +60,10 @@
   /// [EventKind.kServiceRegistered].
   Event _toRegistrationEvent(String method,
           {String kind = EventKind.kServiceRegistered}) =>
-      Event()
-        ..kind = kind
-        ..service = method
-        ..method = method;
+      Event(
+        kind: kind,
+        service: method,
+        method: method,
+        timestamp: DateTime.now().millisecondsSinceEpoch,
+      );
 }
diff --git a/pkg/vm_service/lib/vm_service.dart b/pkg/vm_service/lib/vm_service.dart
index 2838a4e..2850348 100644
--- a/pkg/vm_service/lib/vm_service.dart
+++ b/pkg/vm_service/lib/vm_service.dart
@@ -13,6 +13,8 @@
 import 'dart:convert' show base64, jsonDecode, jsonEncode, utf8;
 import 'dart:typed_data';
 
+import 'package:meta/meta.dart';
+
 import 'src/service_extension_registry.dart';
 
 export 'src/service_extension_registry.dart' show ServiceExtensionRegistry;
@@ -1190,7 +1192,7 @@
           } else if (method.startsWith('ext.')) {
             // Remaining methods with `ext.` are assumed to be registered via
             // dart:developer, which the service implementation handles.
-            var args = params == null ? null : new Map.of(params);
+            var args = params == null ? null : Map.of(params);
             var isolateId = args?.remove('isolateId');
             response = await _serviceImplementation.callServiceExtension(method,
                 isolateId: isolateId, args: args);
@@ -1228,18 +1230,17 @@
   Map<String, ServiceCallback> _services = {};
   Log _log;
 
-  StreamController<String> _onSend = new StreamController.broadcast(sync: true);
-  StreamController<String> _onReceive =
-      new StreamController.broadcast(sync: true);
+  StreamController<String> _onSend = StreamController.broadcast(sync: true);
+  StreamController<String> _onReceive = StreamController.broadcast(sync: true);
 
-  final Completer _onDoneCompleter = new Completer();
+  final Completer _onDoneCompleter = Completer();
 
   Map<String, StreamController<Event>> _eventControllers = {};
 
   StreamController<Event> _getEventController(String eventName) {
     StreamController<Event> controller = _eventControllers[eventName];
     if (controller == null) {
-      controller = new StreamController.broadcast();
+      controller = StreamController.broadcast();
       _eventControllers[eventName] = controller;
     }
     return controller;
@@ -1257,7 +1258,7 @@
     _streamSub = inStream.listen(_processMessage,
         onDone: () => _onDoneCompleter.complete());
     _writeMessage = writeMessage;
-    _log = log == null ? new _NullLog() : log;
+    _log = log == null ? _NullLog() : log;
     _disposeHandler = disposeHandler;
     streamClosed?.then((_) {
       if (!_onDoneCompleter.isCompleted) {
@@ -1671,7 +1672,7 @@
     } else if (args == null) {
       return _call(method, {'isolateId': isolateId});
     } else {
-      args = new Map.from(args);
+      args = Map.from(args);
       if (isolateId != null) {
         args['isolateId'] = isolateId;
       }
@@ -1698,7 +1699,7 @@
 
   Future<T> _call<T>(String method, [Map args]) {
     String id = '${++_id}';
-    Completer<T> completer = new Completer<T>();
+    Completer<T> completer = Completer<T>();
     _completers[id] = completer;
     _methodCalls[id] = method;
     Map m = {'id': id, 'method': method};
@@ -1712,7 +1713,7 @@
   /// Register a service for invocation.
   void registerServiceCallback(String service, ServiceCallback cb) {
     if (_services.containsKey(service)) {
-      throw new Exception('Service \'${service}\' already registered');
+      throw Exception('Service \'${service}\' already registered');
     }
     _services[service] = cb;
   }
@@ -1723,8 +1724,8 @@
     if (message is String) {
       _processMessageStr(message);
     } else if (message is List<int>) {
-      Uint8List list = new Uint8List.fromList(message);
-      _processMessageByteData(new ByteData.view(list.buffer));
+      Uint8List list = Uint8List.fromList(message);
+      _processMessageByteData(ByteData.view(list.buffer));
     } else if (message is ByteData) {
       _processMessageByteData(message);
     } else {
@@ -1736,11 +1737,11 @@
     int offset = 0;
     int metaSize = bytes.getUint32(offset + 4, Endian.big);
     offset += 8;
-    String meta = utf8.decode(new Uint8List.view(
-        bytes.buffer, bytes.offsetInBytes + offset, metaSize));
+    String meta = utf8.decode(
+        Uint8List.view(bytes.buffer, bytes.offsetInBytes + offset, metaSize));
     offset += metaSize;
-    ByteData data = new ByteData.view(bytes.buffer,
-        bytes.offsetInBytes + offset, bytes.lengthInBytes - offset);
+    ByteData data = ByteData.view(bytes.buffer, bytes.offsetInBytes + offset,
+        bytes.lengthInBytes - offset);
     dynamic map = jsonDecode(meta);
     if (map != null && map['method'] == 'streamNotify') {
       String streamId = map['params']['streamId'];
@@ -1842,8 +1843,7 @@
 
 class RPCError {
   static RPCError parse(String callingMethod, dynamic json) {
-    return new RPCError(
-        callingMethod, json['code'], json['message'], json['data']);
+    return RPCError(callingMethod, json['code'], json['message'], json['data']);
   }
 
   final String callingMethod;
@@ -1867,7 +1867,7 @@
 /// An `ExtensionData` is an arbitrary map that can have any contents.
 class ExtensionData {
   static ExtensionData parse(Map json) =>
-      json == null ? null : new ExtensionData._fromJson(json);
+      json == null ? null : ExtensionData._fromJson(json);
 
   final Map data;
 
@@ -2182,7 +2182,7 @@
 
 class AllocationProfile extends Response {
   static AllocationProfile parse(Map<String, dynamic> json) =>
-      json == null ? null : new AllocationProfile._fromJson(json);
+      json == null ? null : AllocationProfile._fromJson(json);
 
   /// Allocation information for all class types.
   List<ClassHeapStats> members;
@@ -2202,11 +2202,15 @@
   @optional
   int dateLastServiceGC;
 
-  AllocationProfile();
-
+  AllocationProfile({
+    @required this.members,
+    @required this.memoryUsage,
+    this.dateLastAccumulatorReset,
+    this.dateLastServiceGC,
+  });
   AllocationProfile._fromJson(Map<String, dynamic> json)
       : super._fromJson(json) {
-    members = new List<ClassHeapStats>.from(
+    members = List<ClassHeapStats>.from(
         createServiceObject(json['members'], const ['ClassHeapStats']));
     memoryUsage =
         createServiceObject(json['memoryUsage'], const ['MemoryUsage']);
@@ -2245,15 +2249,17 @@
 /// `BeingInitialized` [Sentinel].
 class BoundField {
   static BoundField parse(Map<String, dynamic> json) =>
-      json == null ? null : new BoundField._fromJson(json);
+      json == null ? null : BoundField._fromJson(json);
 
   FieldRef decl;
 
   /// [value] can be one of [InstanceRef] or [Sentinel].
   dynamic value;
 
-  BoundField();
-
+  BoundField({
+    @required this.decl,
+    @required this.value,
+  });
   BoundField._fromJson(Map<String, dynamic> json) {
     decl = createServiceObject(json['decl'], const ['FieldRef']);
     value =
@@ -2285,7 +2291,7 @@
 /// the `OptimizedOut` [Sentinel].
 class BoundVariable extends Response {
   static BoundVariable parse(Map<String, dynamic> json) =>
-      json == null ? null : new BoundVariable._fromJson(json);
+      json == null ? null : BoundVariable._fromJson(json);
 
   String name;
 
@@ -2301,8 +2307,13 @@
   /// The last token position where this variable is visible to the scope.
   int scopeEndTokenPos;
 
-  BoundVariable();
-
+  BoundVariable({
+    @required this.name,
+    @required this.value,
+    @required this.declarationTokenPos,
+    @required this.scopeStartTokenPos,
+    @required this.scopeEndTokenPos,
+  });
   BoundVariable._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
     value = createServiceObject(
@@ -2339,7 +2350,7 @@
 /// library).
 class Breakpoint extends Obj {
   static Breakpoint parse(Map<String, dynamic> json) =>
-      json == null ? null : new Breakpoint._fromJson(json);
+      json == null ? null : Breakpoint._fromJson(json);
 
   /// A number identifying this breakpoint to the user.
   int breakpointNumber;
@@ -2358,8 +2369,12 @@
   /// [location] can be one of [SourceLocation] or [UnresolvedSourceLocation].
   dynamic location;
 
-  Breakpoint();
-
+  Breakpoint({
+    @required this.breakpointNumber,
+    @required this.resolved,
+    @required this.location,
+    this.isSyntheticAsyncContinuation,
+  });
   Breakpoint._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     breakpointNumber = json['breakpointNumber'];
     resolved = json['resolved'];
@@ -2394,13 +2409,14 @@
 /// `ClassRef` is a reference to a `Class`.
 class ClassRef extends ObjRef {
   static ClassRef parse(Map<String, dynamic> json) =>
-      json == null ? null : new ClassRef._fromJson(json);
+      json == null ? null : ClassRef._fromJson(json);
 
   /// The name of this class.
   String name;
 
-  ClassRef();
-
+  ClassRef({
+    @required this.name,
+  });
   ClassRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
   }
@@ -2425,7 +2441,7 @@
 /// A `Class` provides information about a Dart language class.
 class Class extends Obj {
   static Class parse(Map<String, dynamic> json) =>
-      json == null ? null : new Class._fromJson(json);
+      json == null ? null : Class._fromJson(json);
 
   /// The name of this class.
   String name;
@@ -2478,8 +2494,21 @@
   /// A list of subclasses of this class.
   List<ClassRef> subclasses;
 
-  Class();
-
+  Class({
+    @required this.name,
+    @required this.isAbstract,
+    @required this.isConst,
+    @required this.library,
+    @required this.interfaces,
+    @required this.fields,
+    @required this.functions,
+    @required this.subclasses,
+    this.error,
+    this.location,
+    this.superClass,
+    this.superType,
+    this.mixin,
+  });
   Class._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
     error = createServiceObject(json['error'], const ['ErrorRef']);
@@ -2489,14 +2518,14 @@
     location = createServiceObject(json['location'], const ['SourceLocation']);
     superClass = createServiceObject(json['super'], const ['ClassRef']);
     superType = createServiceObject(json['superType'], const ['InstanceRef']);
-    interfaces = new List<InstanceRef>.from(
+    interfaces = List<InstanceRef>.from(
         createServiceObject(json['interfaces'], const ['InstanceRef']));
     mixin = createServiceObject(json['mixin'], const ['InstanceRef']);
-    fields = new List<FieldRef>.from(
+    fields = List<FieldRef>.from(
         createServiceObject(json['fields'], const ['FieldRef']));
-    functions = new List<FuncRef>.from(
+    functions = List<FuncRef>.from(
         createServiceObject(json['functions'], const ['FuncRef']));
-    subclasses = new List<ClassRef>.from(
+    subclasses = List<ClassRef>.from(
         createServiceObject(json['subclasses'], const ['ClassRef']));
   }
 
@@ -2531,7 +2560,7 @@
 
 class ClassHeapStats extends Response {
   static ClassHeapStats parse(Map<String, dynamic> json) =>
-      json == null ? null : new ClassHeapStats._fromJson(json);
+      json == null ? null : ClassHeapStats._fromJson(json);
 
   /// The class for which this memory information is associated.
   ClassRef classRef;
@@ -2550,8 +2579,13 @@
   /// The number of instances of class which are currently alive.
   int instancesCurrent;
 
-  ClassHeapStats();
-
+  ClassHeapStats({
+    @required this.classRef,
+    @required this.accumulatedSize,
+    @required this.bytesCurrent,
+    @required this.instancesAccumulated,
+    @required this.instancesCurrent,
+  });
   ClassHeapStats._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     classRef = createServiceObject(json['class'], const ['ClassRef']);
     accumulatedSize = json['accumulatedSize'];
@@ -2581,14 +2615,15 @@
 
 class ClassList extends Response {
   static ClassList parse(Map<String, dynamic> json) =>
-      json == null ? null : new ClassList._fromJson(json);
+      json == null ? null : ClassList._fromJson(json);
 
   List<ClassRef> classes;
 
-  ClassList();
-
+  ClassList({
+    @required this.classes,
+  });
   ClassList._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    classes = new List<ClassRef>.from(
+    classes = List<ClassRef>.from(
         createServiceObject(json['classes'], const ['ClassRef']));
   }
 
@@ -2608,7 +2643,7 @@
 /// `CodeRef` is a reference to a `Code` object.
 class CodeRef extends ObjRef {
   static CodeRef parse(Map<String, dynamic> json) =>
-      json == null ? null : new CodeRef._fromJson(json);
+      json == null ? null : CodeRef._fromJson(json);
 
   /// A name for this code object.
   String name;
@@ -2616,8 +2651,10 @@
   /// What kind of code object is this?
   /*CodeKind*/ String kind;
 
-  CodeRef();
-
+  CodeRef({
+    @required this.name,
+    @required this.kind,
+  });
   CodeRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
     kind = json['kind'];
@@ -2645,7 +2682,7 @@
 /// A `Code` object represents compiled code in the Dart VM.
 class Code extends ObjRef {
   static Code parse(Map<String, dynamic> json) =>
-      json == null ? null : new Code._fromJson(json);
+      json == null ? null : Code._fromJson(json);
 
   /// A name for this code object.
   String name;
@@ -2653,8 +2690,10 @@
   /// What kind of code object is this?
   /*CodeKind*/ String kind;
 
-  Code();
-
+  Code({
+    @required this.name,
+    @required this.kind,
+  });
   Code._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
     kind = json['kind'];
@@ -2681,13 +2720,14 @@
 
 class ContextRef extends ObjRef {
   static ContextRef parse(Map<String, dynamic> json) =>
-      json == null ? null : new ContextRef._fromJson(json);
+      json == null ? null : ContextRef._fromJson(json);
 
   /// The number of variables in this context.
   int length;
 
-  ContextRef();
-
+  ContextRef({
+    @required this.length,
+  });
   ContextRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     length = json['length'];
   }
@@ -2714,7 +2754,7 @@
 /// closure.
 class Context extends Obj {
   static Context parse(Map<String, dynamic> json) =>
-      json == null ? null : new Context._fromJson(json);
+      json == null ? null : Context._fromJson(json);
 
   /// The number of variables in this context.
   int length;
@@ -2726,12 +2766,15 @@
   /// The variables in this context object.
   List<ContextElement> variables;
 
-  Context();
-
+  Context({
+    @required this.length,
+    @required this.variables,
+    this.parent,
+  });
   Context._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     length = json['length'];
     parent = createServiceObject(json['parent'], const ['Context']);
-    variables = new List<ContextElement>.from(
+    variables = List<ContextElement>.from(
         createServiceObject(json['variables'], const ['ContextElement']));
   }
 
@@ -2757,13 +2800,14 @@
 
 class ContextElement {
   static ContextElement parse(Map<String, dynamic> json) =>
-      json == null ? null : new ContextElement._fromJson(json);
+      json == null ? null : ContextElement._fromJson(json);
 
   /// [value] can be one of [InstanceRef] or [Sentinel].
   dynamic value;
 
-  ContextElement();
-
+  ContextElement({
+    @required this.value,
+  });
   ContextElement._fromJson(Map<String, dynamic> json) {
     value =
         createServiceObject(json['value'], const ['InstanceRef', 'Sentinel']);
@@ -2783,7 +2827,7 @@
 /// See [getCpuSamples] and [CpuSample].
 class CpuSamples extends Response {
   static CpuSamples parse(Map<String, dynamic> json) =>
-      json == null ? null : new CpuSamples._fromJson(json);
+      json == null ? null : CpuSamples._fromJson(json);
 
   /// The sampling rate for the profiler in microseconds.
   int samplePeriod;
@@ -2816,8 +2860,17 @@
   /// timeOriginMicros + timeExtentMicros]`
   List<CpuSample> samples;
 
-  CpuSamples();
-
+  CpuSamples({
+    @required this.samplePeriod,
+    @required this.maxStackDepth,
+    @required this.sampleCount,
+    @required this.timeSpan,
+    @required this.timeOriginMicros,
+    @required this.timeExtentMicros,
+    @required this.pid,
+    @required this.functions,
+    @required this.samples,
+  });
   CpuSamples._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     samplePeriod = json['samplePeriod'];
     maxStackDepth = json['maxStackDepth'];
@@ -2826,9 +2879,9 @@
     timeOriginMicros = json['timeOriginMicros'];
     timeExtentMicros = json['timeExtentMicros'];
     pid = json['pid'];
-    functions = new List<ProfileFunction>.from(
+    functions = List<ProfileFunction>.from(
         createServiceObject(json['functions'], const ['ProfileFunction']));
-    samples = new List<CpuSample>.from(
+    samples = List<CpuSample>.from(
         createServiceObject(json['samples'], const ['CpuSample']));
   }
 
@@ -2856,7 +2909,7 @@
 /// See [getCpuSamples] and [CpuSamples].
 class CpuSample {
   static CpuSample parse(Map<String, dynamic> json) =>
-      json == null ? null : new CpuSample._fromJson(json);
+      json == null ? null : CpuSample._fromJson(json);
 
   /// The thread ID representing the thread on which this sample was collected.
   int tid;
@@ -2890,15 +2943,21 @@
   /// @Function(foo())` `functions[stack[2]] = @Function(main())`
   List<int> stack;
 
-  CpuSample();
-
+  CpuSample({
+    @required this.tid,
+    @required this.timestamp,
+    @required this.stack,
+    this.vmTag,
+    this.userTag,
+    this.truncated,
+  });
   CpuSample._fromJson(Map<String, dynamic> json) {
     tid = json['tid'];
     timestamp = json['timestamp'];
     vmTag = json['vmTag'];
     userTag = json['userTag'];
     truncated = json['truncated'];
-    stack = new List<int>.from(json['stack']);
+    stack = List<int>.from(json['stack']);
   }
 
   Map<String, dynamic> toJson() {
@@ -2921,7 +2980,7 @@
 /// `ErrorRef` is a reference to an `Error`.
 class ErrorRef extends ObjRef {
   static ErrorRef parse(Map<String, dynamic> json) =>
-      json == null ? null : new ErrorRef._fromJson(json);
+      json == null ? null : ErrorRef._fromJson(json);
 
   /// What kind of error is this?
   /*ErrorKind*/ String kind;
@@ -2929,8 +2988,10 @@
   /// A description of the error.
   String message;
 
-  ErrorRef();
-
+  ErrorRef({
+    @required this.kind,
+    @required this.message,
+  });
   ErrorRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     kind = json['kind'];
     message = json['message'];
@@ -2959,7 +3020,7 @@
 /// [rpc error].
 class Error extends Obj {
   static Error parse(Map<String, dynamic> json) =>
-      json == null ? null : new Error._fromJson(json);
+      json == null ? null : Error._fromJson(json);
 
   /// What kind of error is this?
   /*ErrorKind*/ String kind;
@@ -2977,8 +3038,12 @@
   @optional
   InstanceRef stacktrace;
 
-  Error();
-
+  Error({
+    @required this.kind,
+    @required this.message,
+    this.exception,
+    this.stacktrace,
+  });
   Error._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     kind = json['kind'];
     message = json['message'];
@@ -3014,7 +3079,7 @@
 /// For more information, see [events].
 class Event extends Response {
   static Event parse(Map<String, dynamic> json) =>
-      json == null ? null : new Event._fromJson(json);
+      json == null ? null : Event._fromJson(json);
 
   /// What kind of event is this?
   /*EventKind*/ String kind;
@@ -3178,8 +3243,30 @@
   @optional
   String newValue;
 
-  Event();
-
+  Event({
+    @required this.kind,
+    @required this.timestamp,
+    this.isolate,
+    this.vm,
+    this.breakpoint,
+    this.pauseBreakpoints,
+    this.topFrame,
+    this.exception,
+    this.bytes,
+    this.inspectee,
+    this.extensionRPC,
+    this.extensionKind,
+    this.extensionData,
+    this.timelineEvents,
+    this.atAsyncSuspension,
+    this.status,
+    this.logRecord,
+    this.service,
+    this.method,
+    this.alias,
+    this.flag,
+    this.newValue,
+  });
   Event._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     kind = json['kind'];
     isolate = createServiceObject(json['isolate'], const ['IsolateRef']);
@@ -3188,7 +3275,7 @@
     breakpoint = createServiceObject(json['breakpoint'], const ['Breakpoint']);
     pauseBreakpoints = json['pauseBreakpoints'] == null
         ? null
-        : new List<Breakpoint>.from(createServiceObject(
+        : List<Breakpoint>.from(createServiceObject(
             json['pauseBreakpoints'], const ['Breakpoint']));
     topFrame = createServiceObject(json['topFrame'], const ['Frame']);
     exception = createServiceObject(json['exception'], const ['InstanceRef']);
@@ -3199,7 +3286,7 @@
     extensionData = ExtensionData.parse(json['extensionData']);
     timelineEvents = json['timelineEvents'] == null
         ? null
-        : new List<TimelineEvent>.from(createServiceObject(
+        : List<TimelineEvent>.from(createServiceObject(
             json['timelineEvents'], const ['TimelineEvent']));
     atAsyncSuspension = json['atAsyncSuspension'];
     status = json['status'];
@@ -3251,7 +3338,7 @@
 /// An `FieldRef` is a reference to a `Field`.
 class FieldRef extends ObjRef {
   static FieldRef parse(Map<String, dynamic> json) =>
-      json == null ? null : new FieldRef._fromJson(json);
+      json == null ? null : FieldRef._fromJson(json);
 
   /// The name of this field.
   String name;
@@ -3274,8 +3361,14 @@
   /// Is this field static?
   bool isStatic;
 
-  FieldRef();
-
+  FieldRef({
+    @required this.name,
+    @required this.owner,
+    @required this.declaredType,
+    @required this.isConst,
+    @required this.isFinal,
+    @required this.isStatic,
+  });
   FieldRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
     owner = createServiceObject(json['owner'], const ['ObjRef']);
@@ -3311,7 +3404,7 @@
 /// A `Field` provides information about a Dart language field or variable.
 class Field extends Obj {
   static Field parse(Map<String, dynamic> json) =>
-      json == null ? null : new Field._fromJson(json);
+      json == null ? null : Field._fromJson(json);
 
   /// The name of this field.
   String name;
@@ -3342,8 +3435,16 @@
   @optional
   SourceLocation location;
 
-  Field();
-
+  Field({
+    @required this.name,
+    @required this.owner,
+    @required this.declaredType,
+    @required this.isConst,
+    @required this.isFinal,
+    @required this.isStatic,
+    this.staticValue,
+    this.location,
+  });
   Field._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
     owner = createServiceObject(json['owner'], const ['ObjRef']);
@@ -3384,7 +3485,7 @@
 /// A `Flag` represents a single VM command line flag.
 class Flag {
   static Flag parse(Map<String, dynamic> json) =>
-      json == null ? null : new Flag._fromJson(json);
+      json == null ? null : Flag._fromJson(json);
 
   /// The name of the flag.
   String name;
@@ -3401,8 +3502,12 @@
   @optional
   String valueAsString;
 
-  Flag();
-
+  Flag({
+    @required this.name,
+    @required this.comment,
+    @required this.modified,
+    this.valueAsString,
+  });
   Flag._fromJson(Map<String, dynamic> json) {
     name = json['name'];
     comment = json['comment'];
@@ -3428,16 +3533,16 @@
 /// A `FlagList` represents the complete set of VM command line flags.
 class FlagList extends Response {
   static FlagList parse(Map<String, dynamic> json) =>
-      json == null ? null : new FlagList._fromJson(json);
+      json == null ? null : FlagList._fromJson(json);
 
   /// A list of all flags in the VM.
   List<Flag> flags;
 
-  FlagList();
-
+  FlagList({
+    @required this.flags,
+  });
   FlagList._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    flags =
-        new List<Flag>.from(createServiceObject(json['flags'], const ['Flag']));
+    flags = List<Flag>.from(createServiceObject(json['flags'], const ['Flag']));
   }
 
   @override
@@ -3455,7 +3560,7 @@
 
 class Frame extends Response {
   static Frame parse(Map<String, dynamic> json) =>
-      json == null ? null : new Frame._fromJson(json);
+      json == null ? null : Frame._fromJson(json);
 
   int index;
 
@@ -3475,8 +3580,14 @@
   /*FrameKind*/
   String kind;
 
-  Frame();
-
+  Frame({
+    @required this.index,
+    this.function,
+    this.code,
+    this.location,
+    this.vars,
+    this.kind,
+  });
   Frame._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     index = json['index'];
     function = createServiceObject(json['function'], const ['FuncRef']);
@@ -3484,7 +3595,7 @@
     location = createServiceObject(json['location'], const ['SourceLocation']);
     vars = json['vars'] == null
         ? null
-        : new List<BoundVariable>.from(
+        : List<BoundVariable>.from(
             createServiceObject(json['vars'], const ['BoundVariable']));
     kind = json['kind'];
   }
@@ -3510,7 +3621,7 @@
 /// An `FuncRef` is a reference to a `Func`.
 class FuncRef extends ObjRef {
   static FuncRef parse(Map<String, dynamic> json) =>
-      json == null ? null : new FuncRef._fromJson(json);
+      json == null ? null : FuncRef._fromJson(json);
 
   /// The name of this function.
   String name;
@@ -3526,8 +3637,12 @@
   /// Is this function const?
   bool isConst;
 
-  FuncRef();
-
+  FuncRef({
+    @required this.name,
+    @required this.owner,
+    @required this.isStatic,
+    @required this.isConst,
+  });
   FuncRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
     owner = createServiceObject(
@@ -3561,7 +3676,7 @@
 /// A `Func` represents a Dart language function.
 class Func extends Obj {
   static Func parse(Map<String, dynamic> json) =>
-      json == null ? null : new Func._fromJson(json);
+      json == null ? null : Func._fromJson(json);
 
   /// The name of this function.
   String name;
@@ -3579,8 +3694,12 @@
   @optional
   CodeRef code;
 
-  Func();
-
+  Func({
+    @required this.name,
+    @required this.owner,
+    this.location,
+    this.code,
+  });
   Func._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
     owner = createServiceObject(
@@ -3613,7 +3732,7 @@
 /// `InstanceRef` is a reference to an `Instance`.
 class InstanceRef extends ObjRef {
   static InstanceRef parse(Map<String, dynamic> json) =>
-      json == null ? null : new InstanceRef._fromJson(json);
+      json == null ? null : InstanceRef._fromJson(json);
 
   /// What kind of instance is this?
   /*InstanceKind*/ String kind;
@@ -3711,8 +3830,19 @@
   @optional
   ContextRef closureContext;
 
-  InstanceRef();
-
+  InstanceRef({
+    @required this.kind,
+    @required this.classRef,
+    this.valueAsString,
+    this.valueAsStringIsTruncated,
+    this.length,
+    this.name,
+    this.typeClass,
+    this.parameterizedClass,
+    this.pattern,
+    this.closureFunction,
+    this.closureContext,
+  });
   InstanceRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     kind = json['kind'];
     classRef = createServiceObject(json['class'], const ['ClassRef']);
@@ -3762,7 +3892,7 @@
 /// An `Instance` represents an instance of the Dart language class `Obj`.
 class Instance extends Obj {
   static Instance parse(Map<String, dynamic> json) =>
-      json == null ? null : new Instance._fromJson(json);
+      json == null ? null : Instance._fromJson(json);
 
   /// What kind of instance is this?
   /*InstanceKind*/ String kind;
@@ -4000,8 +4130,32 @@
   @optional
   InstanceRef bound;
 
-  Instance();
-
+  Instance({
+    @required this.kind,
+    @required this.classRef,
+    this.valueAsString,
+    this.valueAsStringIsTruncated,
+    this.length,
+    this.offset,
+    this.count,
+    this.name,
+    this.typeClass,
+    this.parameterizedClass,
+    this.fields,
+    this.elements,
+    this.associations,
+    this.bytes,
+    this.mirrorReferent,
+    this.pattern,
+    this.isCaseSensitive,
+    this.isMultiLine,
+    this.propertyKey,
+    this.propertyValue,
+    this.typeArguments,
+    this.parameterIndex,
+    this.targetType,
+    this.bound,
+  });
   Instance._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     kind = json['kind'];
     classRef = createServiceObject(json['class'], const ['ClassRef']);
@@ -4016,15 +4170,15 @@
         createServiceObject(json['parameterizedClass'], const ['ClassRef']);
     fields = json['fields'] == null
         ? null
-        : new List<BoundField>.from(
+        : List<BoundField>.from(
             createServiceObject(json['fields'], const ['BoundField']));
     elements = json['elements'] == null
         ? null
-        : new List<dynamic>.from(
+        : List<dynamic>.from(
             createServiceObject(json['elements'], const ['dynamic']));
     associations = json['associations'] == null
         ? null
-        : new List<MapAssociation>.from(
+        : List<MapAssociation>.from(
             _createSpecificObject(json['associations'], MapAssociation.parse));
     bytes = json['bytes'];
     mirrorReferent =
@@ -4090,7 +4244,7 @@
 /// `IsolateRef` is a reference to an `Isolate` object.
 class IsolateRef extends Response {
   static IsolateRef parse(Map<String, dynamic> json) =>
-      json == null ? null : new IsolateRef._fromJson(json);
+      json == null ? null : IsolateRef._fromJson(json);
 
   /// The id which is passed to the getIsolate RPC to load this isolate.
   String id;
@@ -4101,8 +4255,11 @@
   /// A name identifying this isolate. Not guaranteed to be unique.
   String name;
 
-  IsolateRef();
-
+  IsolateRef({
+    @required this.id,
+    @required this.number,
+    @required this.name,
+  });
   IsolateRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     id = json['id'];
     number = json['number'];
@@ -4132,7 +4289,7 @@
 /// An `Isolate` object provides information about one isolate in the VM.
 class Isolate extends Response {
   static Isolate parse(Map<String, dynamic> json) =>
-      json == null ? null : new Isolate._fromJson(json);
+      json == null ? null : Isolate._fromJson(json);
 
   /// The id which is passed to the getIsolate RPC to reload this isolate.
   String id;
@@ -4187,8 +4344,22 @@
   @optional
   List<String> extensionRPCs;
 
-  Isolate();
-
+  Isolate({
+    @required this.id,
+    @required this.number,
+    @required this.name,
+    @required this.startTime,
+    @required this.runnable,
+    @required this.livePorts,
+    @required this.pauseOnExit,
+    @required this.pauseEvent,
+    @required this.libraries,
+    @required this.breakpoints,
+    @required this.exceptionPauseMode,
+    this.rootLib,
+    this.error,
+    this.extensionRPCs,
+  });
   Isolate._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     id = json['id'];
     number = json['number'];
@@ -4199,15 +4370,15 @@
     pauseOnExit = json['pauseOnExit'];
     pauseEvent = createServiceObject(json['pauseEvent'], const ['Event']);
     rootLib = createServiceObject(json['rootLib'], const ['LibraryRef']);
-    libraries = new List<LibraryRef>.from(
+    libraries = List<LibraryRef>.from(
         createServiceObject(json['libraries'], const ['LibraryRef']));
-    breakpoints = new List<Breakpoint>.from(
+    breakpoints = List<Breakpoint>.from(
         createServiceObject(json['breakpoints'], const ['Breakpoint']));
     error = createServiceObject(json['error'], const ['Error']);
     exceptionPauseMode = json['exceptionPauseMode'];
     extensionRPCs = json['extensionRPCs'] == null
         ? null
-        : new List<String>.from(json['extensionRPCs']);
+        : List<String>.from(json['extensionRPCs']);
   }
 
   @override
@@ -4244,16 +4415,17 @@
 /// See [getInboundReferences].
 class InboundReferences extends Response {
   static InboundReferences parse(Map<String, dynamic> json) =>
-      json == null ? null : new InboundReferences._fromJson(json);
+      json == null ? null : InboundReferences._fromJson(json);
 
   /// An array of inbound references to an object.
   List<InboundReference> references;
 
-  InboundReferences();
-
+  InboundReferences({
+    @required this.references,
+  });
   InboundReferences._fromJson(Map<String, dynamic> json)
       : super._fromJson(json) {
-    references = new List<InboundReference>.from(
+    references = List<InboundReference>.from(
         createServiceObject(json['references'], const ['InboundReference']));
   }
 
@@ -4274,7 +4446,7 @@
 /// See [getInboundReferences].
 class InboundReference {
   static InboundReference parse(Map<String, dynamic> json) =>
-      json == null ? null : new InboundReference._fromJson(json);
+      json == null ? null : InboundReference._fromJson(json);
 
   /// The object holding the inbound reference.
   ObjRef source;
@@ -4289,8 +4461,11 @@
   @optional
   FieldRef parentField;
 
-  InboundReference();
-
+  InboundReference({
+    @required this.source,
+    this.parentListIndex,
+    this.parentField,
+  });
   InboundReference._fromJson(Map<String, dynamic> json) {
     source = createServiceObject(json['source'], const ['ObjRef']);
     parentListIndex = json['parentListIndex'];
@@ -4313,7 +4488,7 @@
 /// See [getInstances].
 class InstanceSet extends Response {
   static InstanceSet parse(Map<String, dynamic> json) =>
-      json == null ? null : new InstanceSet._fromJson(json);
+      json == null ? null : InstanceSet._fromJson(json);
 
   /// The number of instances of the requested type currently allocated.
   int totalCount;
@@ -4321,11 +4496,13 @@
   /// An array of instances of the requested type.
   List<ObjRef> instances;
 
-  InstanceSet();
-
+  InstanceSet({
+    @required this.totalCount,
+    @required this.instances,
+  });
   InstanceSet._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     totalCount = json['totalCount'];
-    instances = new List<ObjRef>.from(createServiceObject(
+    instances = List<ObjRef>.from(createServiceObject(
         json['instances'] ?? json['samples'], const ['ObjRef']));
   }
 
@@ -4347,7 +4524,7 @@
 /// `LibraryRef` is a reference to a `Library`.
 class LibraryRef extends ObjRef {
   static LibraryRef parse(Map<String, dynamic> json) =>
-      json == null ? null : new LibraryRef._fromJson(json);
+      json == null ? null : LibraryRef._fromJson(json);
 
   /// The name of this library.
   String name;
@@ -4355,8 +4532,10 @@
   /// The uri of this library.
   String uri;
 
-  LibraryRef();
-
+  LibraryRef({
+    @required this.name,
+    @required this.uri,
+  });
   LibraryRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
     uri = json['uri'];
@@ -4386,7 +4565,7 @@
 /// See [setLibraryDebuggable].
 class Library extends Obj {
   static Library parse(Map<String, dynamic> json) =>
-      json == null ? null : new Library._fromJson(json);
+      json == null ? null : Library._fromJson(json);
 
   /// The name of this library.
   String name;
@@ -4412,21 +4591,29 @@
   /// A list of all classes in this library.
   List<ClassRef> classes;
 
-  Library();
-
+  Library({
+    @required this.name,
+    @required this.uri,
+    @required this.debuggable,
+    @required this.dependencies,
+    @required this.scripts,
+    @required this.variables,
+    @required this.functions,
+    @required this.classes,
+  });
   Library._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
     uri = json['uri'];
     debuggable = json['debuggable'];
-    dependencies = new List<LibraryDependency>.from(
+    dependencies = List<LibraryDependency>.from(
         _createSpecificObject(json['dependencies'], LibraryDependency.parse));
-    scripts = new List<ScriptRef>.from(
+    scripts = List<ScriptRef>.from(
         createServiceObject(json['scripts'], const ['ScriptRef']));
-    variables = new List<FieldRef>.from(
+    variables = List<FieldRef>.from(
         createServiceObject(json['variables'], const ['FieldRef']));
-    functions = new List<FuncRef>.from(
+    functions = List<FuncRef>.from(
         createServiceObject(json['functions'], const ['FuncRef']));
-    classes = new List<ClassRef>.from(
+    classes = List<ClassRef>.from(
         createServiceObject(json['classes'], const ['ClassRef']));
   }
 
@@ -4457,7 +4644,7 @@
 /// A `LibraryDependency` provides information about an import or export.
 class LibraryDependency {
   static LibraryDependency parse(Map<String, dynamic> json) =>
-      json == null ? null : new LibraryDependency._fromJson(json);
+      json == null ? null : LibraryDependency._fromJson(json);
 
   /// Is this dependency an import (rather than an export)?
   bool isImport;
@@ -4471,8 +4658,12 @@
   /// The library being imported or exported.
   LibraryRef target;
 
-  LibraryDependency();
-
+  LibraryDependency({
+    @required this.isImport,
+    @required this.isDeferred,
+    @required this.prefix,
+    @required this.target,
+  });
   LibraryDependency._fromJson(Map<String, dynamic> json) {
     isImport = json['isImport'];
     isDeferred = json['isDeferred'];
@@ -4498,7 +4689,7 @@
 
 class LogRecord extends Response {
   static LogRecord parse(Map<String, dynamic> json) =>
-      json == null ? null : new LogRecord._fromJson(json);
+      json == null ? null : LogRecord._fromJson(json);
 
   /// The log message.
   InstanceRef message;
@@ -4527,8 +4718,16 @@
   /// A stack trace associated with this log event.
   InstanceRef stackTrace;
 
-  LogRecord();
-
+  LogRecord({
+    @required this.message,
+    @required this.time,
+    @required this.level,
+    @required this.sequenceNumber,
+    @required this.loggerName,
+    @required this.zone,
+    @required this.error,
+    @required this.stackTrace,
+  });
   LogRecord._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     message = createServiceObject(json['message'], const ['InstanceRef']);
     time = json['time'];
@@ -4562,7 +4761,7 @@
 
 class MapAssociation {
   static MapAssociation parse(Map<String, dynamic> json) =>
-      json == null ? null : new MapAssociation._fromJson(json);
+      json == null ? null : MapAssociation._fromJson(json);
 
   /// [key] can be one of [InstanceRef] or [Sentinel].
   dynamic key;
@@ -4570,8 +4769,10 @@
   /// [value] can be one of [InstanceRef] or [Sentinel].
   dynamic value;
 
-  MapAssociation();
-
+  MapAssociation({
+    @required this.key,
+    @required this.value,
+  });
   MapAssociation._fromJson(Map<String, dynamic> json) {
     key = createServiceObject(json['key'], const ['InstanceRef', 'Sentinel']);
     value =
@@ -4594,7 +4795,7 @@
 /// isolate at a given point in time.
 class MemoryUsage extends Response {
   static MemoryUsage parse(Map<String, dynamic> json) =>
-      json == null ? null : new MemoryUsage._fromJson(json);
+      json == null ? null : MemoryUsage._fromJson(json);
 
   /// The amount of non-Dart memory that is retained by Dart objects. For
   /// example, memory associated with Dart objects through APIs such as
@@ -4612,8 +4813,11 @@
   /// equal to the heap capacity.
   int heapUsage;
 
-  MemoryUsage();
-
+  MemoryUsage({
+    @required this.externalUsage,
+    @required this.heapCapacity,
+    @required this.heapUsage,
+  });
   MemoryUsage._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     externalUsage = json['externalUsage'];
     heapCapacity = json['heapCapacity'];
@@ -4641,7 +4845,7 @@
 /// function that will be invoked to handle it.
 class Message extends Response {
   static Message parse(Map<String, dynamic> json) =>
-      json == null ? null : new Message._fromJson(json);
+      json == null ? null : Message._fromJson(json);
 
   /// The index in the isolate's message queue. The 0th message being the next
   /// message to be processed.
@@ -4665,8 +4869,14 @@
   @optional
   SourceLocation location;
 
-  Message();
-
+  Message({
+    @required this.index,
+    @required this.name,
+    @required this.messageObjectId,
+    @required this.size,
+    this.handler,
+    this.location,
+  });
   Message._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     index = json['index'];
     name = json['name'];
@@ -4700,13 +4910,14 @@
 /// samples. See [CpuSamples];
 class NativeFunction {
   static NativeFunction parse(Map<String, dynamic> json) =>
-      json == null ? null : new NativeFunction._fromJson(json);
+      json == null ? null : NativeFunction._fromJson(json);
 
   /// The name of the native function this object represents.
   String name;
 
-  NativeFunction();
-
+  NativeFunction({
+    @required this.name,
+  });
   NativeFunction._fromJson(Map<String, dynamic> json) {
     name = json['name'];
   }
@@ -4725,14 +4936,15 @@
 /// `NullValRef` is a reference to an a `NullVal`.
 class NullValRef extends InstanceRef {
   static NullValRef parse(Map<String, dynamic> json) =>
-      json == null ? null : new NullValRef._fromJson(json);
+      json == null ? null : NullValRef._fromJson(json);
 
   /// Always 'null'.
   @override
   String valueAsString;
 
-  NullValRef();
-
+  NullValRef({
+    @required this.valueAsString,
+  });
   NullValRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     valueAsString = json['valueAsString'];
   }
@@ -4759,14 +4971,15 @@
 /// A `NullVal` object represents the Dart language value null.
 class NullVal extends Instance {
   static NullVal parse(Map<String, dynamic> json) =>
-      json == null ? null : new NullVal._fromJson(json);
+      json == null ? null : NullVal._fromJson(json);
 
   /// Always 'null'.
   @override
   String valueAsString;
 
-  NullVal();
-
+  NullVal({
+    @required this.valueAsString,
+  });
   NullVal._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     valueAsString = json['valueAsString'];
   }
@@ -4793,7 +5006,7 @@
 /// `ObjRef` is a reference to a `Obj`.
 class ObjRef extends Response {
   static ObjRef parse(Map<String, dynamic> json) =>
-      json == null ? null : new ObjRef._fromJson(json);
+      json == null ? null : ObjRef._fromJson(json);
 
   /// A unique identifier for an Object. Passed to the getObject RPC to load
   /// this Object.
@@ -4805,8 +5018,10 @@
   @optional
   bool fixedId;
 
-  ObjRef();
-
+  ObjRef({
+    @required this.id,
+    this.fixedId,
+  });
   ObjRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     id = json['id'];
     fixedId = json['fixedId'];
@@ -4833,7 +5048,7 @@
 /// An `Obj` is a persistent object that is owned by some isolate.
 class Obj extends Response {
   static Obj parse(Map<String, dynamic> json) =>
-      json == null ? null : new Obj._fromJson(json);
+      json == null ? null : Obj._fromJson(json);
 
   /// A unique identifier for an Object. Passed to the getObject RPC to reload
   /// this Object.
@@ -4868,8 +5083,12 @@
   @optional
   int size;
 
-  Obj();
-
+  Obj({
+    @required this.id,
+    this.fixedId,
+    this.classRef,
+    this.size,
+  });
   Obj._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     id = json['id'];
     fixedId = json['fixedId'];
@@ -4903,7 +5122,7 @@
 /// See [CpuSamples].
 class ProfileFunction {
   static ProfileFunction parse(Map<String, dynamic> json) =>
-      json == null ? null : new ProfileFunction._fromJson(json);
+      json == null ? null : ProfileFunction._fromJson(json);
 
   /// The kind of function this object represents.
   String kind;
@@ -4921,8 +5140,13 @@
   /// The function captured during profiling.
   dynamic function;
 
-  ProfileFunction();
-
+  ProfileFunction({
+    @required this.kind,
+    @required this.inclusiveTicks,
+    @required this.exclusiveTicks,
+    @required this.resolvedUrl,
+    @required this.function,
+  });
   ProfileFunction._fromJson(Map<String, dynamic> json) {
     kind = json['kind'];
     inclusiveTicks = json['inclusiveTicks'];
@@ -4950,13 +5174,14 @@
 
 class ReloadReport extends Response {
   static ReloadReport parse(Map<String, dynamic> json) =>
-      json == null ? null : new ReloadReport._fromJson(json);
+      json == null ? null : ReloadReport._fromJson(json);
 
   /// Did the reload succeed or fail?
   bool success;
 
-  ReloadReport();
-
+  ReloadReport({
+    @required this.success,
+  });
   ReloadReport._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     success = json['success'];
   }
@@ -4977,7 +5202,7 @@
 /// See [RetainingPath].
 class RetainingObject {
   static RetainingObject parse(Map<String, dynamic> json) =>
-      json == null ? null : new RetainingObject._fromJson(json);
+      json == null ? null : RetainingObject._fromJson(json);
 
   /// An object that is part of a retaining path.
   ObjRef value;
@@ -4994,8 +5219,12 @@
   @optional
   String parentField;
 
-  RetainingObject();
-
+  RetainingObject({
+    @required this.value,
+    this.parentListIndex,
+    this.parentMapKey,
+    this.parentField,
+  });
   RetainingObject._fromJson(Map<String, dynamic> json) {
     value = createServiceObject(json['value'], const ['ObjRef']);
     parentListIndex = json['parentListIndex'];
@@ -5020,7 +5249,7 @@
 /// See [getRetainingPath].
 class RetainingPath extends Response {
   static RetainingPath parse(Map<String, dynamic> json) =>
-      json == null ? null : new RetainingPath._fromJson(json);
+      json == null ? null : RetainingPath._fromJson(json);
 
   /// The length of the retaining path.
   int length;
@@ -5033,12 +5262,15 @@
   /// The chain of objects which make up the retaining path.
   List<RetainingObject> elements;
 
-  RetainingPath();
-
+  RetainingPath({
+    @required this.length,
+    @required this.gcRootType,
+    @required this.elements,
+  });
   RetainingPath._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     length = json['length'];
     gcRootType = json['gcRootType'];
-    elements = new List<RetainingObject>.from(
+    elements = List<RetainingObject>.from(
         createServiceObject(json['elements'], const ['RetainingObject']));
   }
 
@@ -5064,7 +5296,7 @@
 /// [type] of response has been provided.
 class Response {
   static Response parse(Map<String, dynamic> json) =>
-      json == null ? null : new Response._fromJson(json);
+      json == null ? null : Response._fromJson(json);
 
   Map<String, dynamic> json;
 
@@ -5072,8 +5304,9 @@
   /// allows the client distinguish between different kinds of responses.
   String type;
 
-  Response();
-
+  Response({
+    @required this.type,
+  });
   Response._fromJson(this.json) {
     type = json['type'];
   }
@@ -5093,7 +5326,7 @@
 /// not represent a problematic condition. They are normal.
 class Sentinel extends Response {
   static Sentinel parse(Map<String, dynamic> json) =>
-      json == null ? null : new Sentinel._fromJson(json);
+      json == null ? null : Sentinel._fromJson(json);
 
   /// What kind of sentinel is this?
   /*SentinelKind*/ String kind;
@@ -5101,8 +5334,10 @@
   /// A reasonable string representation of this sentinel.
   String valueAsString;
 
-  Sentinel();
-
+  Sentinel({
+    @required this.kind,
+    @required this.valueAsString,
+  });
   Sentinel._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     kind = json['kind'];
     valueAsString = json['valueAsString'];
@@ -5126,13 +5361,14 @@
 /// `ScriptRef` is a reference to a `Script`.
 class ScriptRef extends ObjRef {
   static ScriptRef parse(Map<String, dynamic> json) =>
-      json == null ? null : new ScriptRef._fromJson(json);
+      json == null ? null : ScriptRef._fromJson(json);
 
   /// The uri from which this script was loaded.
   String uri;
 
-  ScriptRef();
-
+  ScriptRef({
+    @required this.uri,
+  });
   ScriptRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     uri = json['uri'];
   }
@@ -5186,7 +5422,7 @@
 /// 102 | 2 | 7
 class Script extends Obj {
   static Script parse(Map<String, dynamic> json) =>
-      json == null ? null : new Script._fromJson(json);
+      json == null ? null : Script._fromJson(json);
 
   /// The uri from which this script was loaded.
   String uri;
@@ -5210,8 +5446,14 @@
   @optional
   List<List<int>> tokenPosTable;
 
-  Script();
-
+  Script({
+    @required this.uri,
+    @required this.library,
+    this.lineOffset,
+    this.columnOffset,
+    this.source,
+    this.tokenPosTable,
+  });
   Script._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     uri = json['uri'];
     library = createServiceObject(json['library'], const ['LibraryRef']);
@@ -5220,8 +5462,8 @@
     source = json['source'];
     tokenPosTable = json['tokenPosTable'] == null
         ? null
-        : new List<List<int>>.from(json['tokenPosTable']
-            .map((dynamic list) => new List<int>.from(list)));
+        : List<List<int>>.from(
+            json['tokenPosTable'].map((dynamic list) => List<int>.from(list)));
   }
 
   @override
@@ -5250,14 +5492,15 @@
 
 class ScriptList extends Response {
   static ScriptList parse(Map<String, dynamic> json) =>
-      json == null ? null : new ScriptList._fromJson(json);
+      json == null ? null : ScriptList._fromJson(json);
 
   List<ScriptRef> scripts;
 
-  ScriptList();
-
+  ScriptList({
+    @required this.scripts,
+  });
   ScriptList._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    scripts = new List<ScriptRef>.from(
+    scripts = List<ScriptRef>.from(
         createServiceObject(json['scripts'], const ['ScriptRef']));
   }
 
@@ -5278,7 +5521,7 @@
 /// script.
 class SourceLocation extends Response {
   static SourceLocation parse(Map<String, dynamic> json) =>
-      json == null ? null : new SourceLocation._fromJson(json);
+      json == null ? null : SourceLocation._fromJson(json);
 
   /// The script containing the source location.
   ScriptRef script;
@@ -5290,8 +5533,11 @@
   @optional
   int endTokenPos;
 
-  SourceLocation();
-
+  SourceLocation({
+    @required this.script,
+    @required this.tokenPos,
+    this.endTokenPos,
+  });
   SourceLocation._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     script = createServiceObject(json['script'], const ['ScriptRef']);
     tokenPos = json['tokenPos'];
@@ -5318,7 +5564,7 @@
 /// locations in an isolate.
 class SourceReport extends Response {
   static SourceReport parse(Map<String, dynamic> json) =>
-      json == null ? null : new SourceReport._fromJson(json);
+      json == null ? null : SourceReport._fromJson(json);
 
   /// A list of ranges in the program source.  These ranges correspond to ranges
   /// of executable code in the user's program (functions, methods,
@@ -5333,12 +5579,14 @@
   /// A list of scripts, referenced by index in the report's ranges.
   List<ScriptRef> scripts;
 
-  SourceReport();
-
+  SourceReport({
+    @required this.ranges,
+    @required this.scripts,
+  });
   SourceReport._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    ranges = new List<SourceReportRange>.from(
+    ranges = List<SourceReportRange>.from(
         _createSpecificObject(json['ranges'], SourceReportRange.parse));
-    scripts = new List<ScriptRef>.from(
+    scripts = List<ScriptRef>.from(
         createServiceObject(json['scripts'], const ['ScriptRef']));
   }
 
@@ -5364,7 +5612,7 @@
 /// will not contain a `type` property.
 class SourceReportCoverage {
   static SourceReportCoverage parse(Map<String, dynamic> json) =>
-      json == null ? null : new SourceReportCoverage._fromJson(json);
+      json == null ? null : SourceReportCoverage._fromJson(json);
 
   /// A list of token positions in a SourceReportRange which have been executed.
   /// The list is sorted.
@@ -5374,11 +5622,13 @@
   /// executed.  The list is sorted.
   List<int> misses;
 
-  SourceReportCoverage();
-
+  SourceReportCoverage({
+    @required this.hits,
+    @required this.misses,
+  });
   SourceReportCoverage._fromJson(Map<String, dynamic> json) {
-    hits = new List<int>.from(json['hits']);
-    misses = new List<int>.from(json['misses']);
+    hits = List<int>.from(json['hits']);
+    misses = List<int>.from(json['misses']);
   }
 
   Map<String, dynamic> toJson() {
@@ -5402,7 +5652,7 @@
 /// not contain a `type` property.
 class SourceReportRange {
   static SourceReportRange parse(Map<String, dynamic> json) =>
-      json == null ? null : new SourceReportRange._fromJson(json);
+      json == null ? null : SourceReportRange._fromJson(json);
 
   /// An index into the script table of the SourceReport, indicating which
   /// script contains this range of code.
@@ -5434,8 +5684,15 @@
   @optional
   List<int> possibleBreakpoints;
 
-  SourceReportRange();
-
+  SourceReportRange({
+    @required this.scriptIndex,
+    @required this.startPos,
+    @required this.endPos,
+    @required this.compiled,
+    this.error,
+    this.coverage,
+    this.possibleBreakpoints,
+  });
   SourceReportRange._fromJson(Map<String, dynamic> json) {
     scriptIndex = json['scriptIndex'];
     startPos = json['startPos'];
@@ -5446,7 +5703,7 @@
         _createSpecificObject(json['coverage'], SourceReportCoverage.parse);
     possibleBreakpoints = json['possibleBreakpoints'] == null
         ? null
-        : new List<int>.from(json['possibleBreakpoints']);
+        : List<int>.from(json['possibleBreakpoints']);
   }
 
   Map<String, dynamic> toJson() {
@@ -5471,7 +5728,7 @@
 
 class Stack extends Response {
   static Stack parse(Map<String, dynamic> json) =>
-      json == null ? null : new Stack._fromJson(json);
+      json == null ? null : Stack._fromJson(json);
 
   List<Frame> frames;
 
@@ -5483,20 +5740,24 @@
 
   List<Message> messages;
 
-  Stack();
-
+  Stack({
+    @required this.frames,
+    @required this.messages,
+    this.asyncCausalFrames,
+    this.awaiterFrames,
+  });
   Stack._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    frames = new List<Frame>.from(
-        createServiceObject(json['frames'], const ['Frame']));
+    frames =
+        List<Frame>.from(createServiceObject(json['frames'], const ['Frame']));
     asyncCausalFrames = json['asyncCausalFrames'] == null
         ? null
-        : new List<Frame>.from(
+        : List<Frame>.from(
             createServiceObject(json['asyncCausalFrames'], const ['Frame']));
     awaiterFrames = json['awaiterFrames'] == null
         ? null
-        : new List<Frame>.from(
+        : List<Frame>.from(
             createServiceObject(json['awaiterFrames'], const ['Frame']));
-    messages = new List<Message>.from(
+    messages = List<Message>.from(
         createServiceObject(json['messages'], const ['Message']));
   }
 
@@ -5523,10 +5784,9 @@
 /// successfully.
 class Success extends Response {
   static Success parse(Map<String, dynamic> json) =>
-      json == null ? null : new Success._fromJson(json);
+      json == null ? null : Success._fromJson(json);
 
   Success();
-
   Success._fromJson(Map<String, dynamic> json) : super._fromJson(json);
 
   @override
@@ -5541,7 +5801,7 @@
 
 class Timeline extends Response {
   static Timeline parse(Map<String, dynamic> json) =>
-      json == null ? null : new Timeline._fromJson(json);
+      json == null ? null : Timeline._fromJson(json);
 
   /// A list of timeline events.
   List<TimelineEvent> traceEvents;
@@ -5552,10 +5812,13 @@
   /// The duration of time covered by the timeline.
   int timeExtentMicros;
 
-  Timeline();
-
+  Timeline({
+    @required this.traceEvents,
+    @required this.timeOriginMicros,
+    @required this.timeExtentMicros,
+  });
   Timeline._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    traceEvents = new List<TimelineEvent>.from(
+    traceEvents = List<TimelineEvent>.from(
         createServiceObject(json['traceEvents'], const ['TimelineEvent']));
     timeOriginMicros = json['timeOriginMicros'];
     timeExtentMicros = json['timeExtentMicros'];
@@ -5582,10 +5845,9 @@
 /// event.
 class TimelineEvent {
   static TimelineEvent parse(Map<String, dynamic> json) =>
-      json == null ? null : new TimelineEvent._fromJson(json);
+      json == null ? null : TimelineEvent._fromJson(json);
 
   TimelineEvent();
-
   TimelineEvent._fromJson(Map<String, dynamic> json);
 
   Map<String, dynamic> toJson() {
@@ -5598,7 +5860,7 @@
 
 class TimelineFlags extends Response {
   static TimelineFlags parse(Map<String, dynamic> json) =>
-      json == null ? null : new TimelineFlags._fromJson(json);
+      json == null ? null : TimelineFlags._fromJson(json);
 
   /// The name of the recorder currently in use. Recorder types include, but are
   /// not limited to: Callback, Endless, Fuchsia, Ring, Startup, and Systrace.
@@ -5611,12 +5873,15 @@
   /// The list of timeline streams that are currently enabled.
   List<String> recordedStreams;
 
-  TimelineFlags();
-
+  TimelineFlags({
+    @required this.recorderName,
+    @required this.availableStreams,
+    @required this.recordedStreams,
+  });
   TimelineFlags._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     recorderName = json['recorderName'];
-    availableStreams = new List<String>.from(json['availableStreams']);
-    recordedStreams = new List<String>.from(json['recordedStreams']);
+    availableStreams = List<String>.from(json['availableStreams']);
+    recordedStreams = List<String>.from(json['recordedStreams']);
   }
 
   @override
@@ -5638,13 +5903,14 @@
 
 class Timestamp extends Response {
   static Timestamp parse(Map<String, dynamic> json) =>
-      json == null ? null : new Timestamp._fromJson(json);
+      json == null ? null : Timestamp._fromJson(json);
 
   /// A timestamp in microseconds since epoch.
   int timestamp;
 
-  Timestamp();
-
+  Timestamp({
+    @required this.timestamp,
+  });
   Timestamp._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     timestamp = json['timestamp'];
   }
@@ -5665,13 +5931,14 @@
 /// `TypeArgumentsRef` is a reference to a `TypeArguments` object.
 class TypeArgumentsRef extends ObjRef {
   static TypeArgumentsRef parse(Map<String, dynamic> json) =>
-      json == null ? null : new TypeArgumentsRef._fromJson(json);
+      json == null ? null : TypeArgumentsRef._fromJson(json);
 
   /// A name for this type argument list.
   String name;
 
-  TypeArgumentsRef();
-
+  TypeArgumentsRef({
+    @required this.name,
+  });
   TypeArgumentsRef._fromJson(Map<String, dynamic> json)
       : super._fromJson(json) {
     name = json['name'];
@@ -5699,7 +5966,7 @@
 /// instantiated generic type.
 class TypeArguments extends Obj {
   static TypeArguments parse(Map<String, dynamic> json) =>
-      json == null ? null : new TypeArguments._fromJson(json);
+      json == null ? null : TypeArguments._fromJson(json);
 
   /// A name for this type argument list.
   String name;
@@ -5710,11 +5977,13 @@
   /// BoundedType.
   List<InstanceRef> types;
 
-  TypeArguments();
-
+  TypeArguments({
+    @required this.name,
+    @required this.types,
+  });
   TypeArguments._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
-    types = new List<InstanceRef>.from(
+    types = List<InstanceRef>.from(
         createServiceObject(json['types'], const ['InstanceRef']));
   }
 
@@ -5749,7 +6018,7 @@
 /// with a specific column number.
 class UnresolvedSourceLocation extends Response {
   static UnresolvedSourceLocation parse(Map<String, dynamic> json) =>
-      json == null ? null : new UnresolvedSourceLocation._fromJson(json);
+      json == null ? null : UnresolvedSourceLocation._fromJson(json);
 
   /// The script containing the source location if the script has been loaded.
   @optional
@@ -5775,8 +6044,13 @@
   @optional
   int column;
 
-  UnresolvedSourceLocation();
-
+  UnresolvedSourceLocation({
+    this.script,
+    this.scriptUri,
+    this.tokenPos,
+    this.line,
+    this.column,
+  });
   UnresolvedSourceLocation._fromJson(Map<String, dynamic> json)
       : super._fromJson(json) {
     script = createServiceObject(json['script'], const ['ScriptRef']);
@@ -5804,7 +6078,7 @@
 /// See [Versioning].
 class Version extends Response {
   static Version parse(Map<String, dynamic> json) =>
-      json == null ? null : new Version._fromJson(json);
+      json == null ? null : Version._fromJson(json);
 
   /// The major version number is incremented when the protocol is changed in a
   /// potentially incompatible way.
@@ -5814,8 +6088,10 @@
   /// backwards compatible way.
   int minor;
 
-  Version();
-
+  Version({
+    @required this.major,
+    @required this.minor,
+  });
   Version._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     major = json['major'];
     minor = json['minor'];
@@ -5839,13 +6115,14 @@
 /// `VMRef` is a reference to a `VM` object.
 class VMRef extends Response {
   static VMRef parse(Map<String, dynamic> json) =>
-      json == null ? null : new VMRef._fromJson(json);
+      json == null ? null : VMRef._fromJson(json);
 
   /// A name identifying this vm. Not guaranteed to be unique.
   String name;
 
-  VMRef();
-
+  VMRef({
+    @required this.name,
+  });
   VMRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
   }
@@ -5865,7 +6142,7 @@
 
 class VM extends Response {
   static VM parse(Map<String, dynamic> json) =>
-      json == null ? null : new VM._fromJson(json);
+      json == null ? null : VM._fromJson(json);
 
   /// A name identifying this vm. Not guaranteed to be unique.
   String name;
@@ -5896,8 +6173,17 @@
   /// A list of isolates running in the VM.
   List<IsolateRef> isolates;
 
-  VM();
-
+  VM({
+    @required this.name,
+    @required this.architectureBits,
+    @required this.hostCPU,
+    @required this.operatingSystem,
+    @required this.targetCPU,
+    @required this.version,
+    @required this.pid,
+    @required this.startTime,
+    @required this.isolates,
+  });
   VM._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
     architectureBits = json['architectureBits'];
@@ -5907,7 +6193,7 @@
     version = json['version'];
     pid = json['pid'];
     startTime = json['startTime'];
-    isolates = new List<IsolateRef>.from(
+    isolates = List<IsolateRef>.from(
         createServiceObject(json['isolates'], const ['IsolateRef']));
   }
 
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index d5e62e2..af6597f 100644
--- a/pkg/vm_service/pubspec.yaml
+++ b/pkg/vm_service/pubspec.yaml
@@ -2,7 +2,7 @@
 description: >-
   A library to communicate with a service implementing the Dart VM
   service protocol.
-version: 1.2.0
+version: 2.0.0
 
 author: Dart Team <misc@dartlang.org>
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/vm_service
diff --git a/pkg/vm_service/test/server_test.dart b/pkg/vm_service/test/server_test.dart
index 4fdee8f..62a351f 100644
--- a/pkg/vm_service/test/server_test.dart
+++ b/pkg/vm_service/test/server_test.dart
@@ -35,27 +35,29 @@
   group('method delegation', () {
     test('works for simple methods', () {
       var request = rpcRequest("getVersion");
-      var version = Version()
-        ..major = 1
-        ..minor = 0;
+      var version = Version(major: 1, minor: 0);
       when(serviceMock.getVersion()).thenAnswer((_) => Future.value(version));
       expect(responsesController.stream, emits(rpcResponse(version)));
       requestsController.add(request);
     });
 
     test('works for methods with parameters', () {
-      var isolate = Isolate()
-        ..id = '123'
-        ..number = '0'
-        ..startTime = 1
-        ..runnable = true
-        ..livePorts = 2
-        ..pauseOnExit = false
-        ..pauseEvent = (Event()
-          ..kind = EventKind.kResume
-          ..timestamp = 3)
-        ..libraries = []
-        ..breakpoints = [];
+      var isolate = Isolate(
+        name: 'isolate',
+        exceptionPauseMode: ExceptionPauseMode.kNone,
+        id: '123',
+        number: '0',
+        startTime: 1,
+        runnable: true,
+        livePorts: 2,
+        pauseOnExit: false,
+        pauseEvent: Event(
+          kind: EventKind.kResume,
+          timestamp: 3,
+        ),
+        libraries: [],
+        breakpoints: [],
+      );
       var request = rpcRequest("getIsolate", params: {'isolateId': isolate.id});
       when(serviceMock.getIsolate(isolate.id))
           .thenAnswer((Invocation invocation) {
@@ -67,18 +69,22 @@
     });
 
     test('works for methods with list parameters', () {
-      var isolate = Isolate()
-        ..id = '123'
-        ..number = '0'
-        ..startTime = 1
-        ..runnable = true
-        ..livePorts = 2
-        ..pauseOnExit = false
-        ..pauseEvent = (Event()
-          ..kind = EventKind.kResume
-          ..timestamp = 3)
-        ..libraries = []
-        ..breakpoints = [];
+      var isolate = Isolate(
+        name: 'isolate',
+        exceptionPauseMode: ExceptionPauseMode.kNone,
+        id: '123',
+        number: '0',
+        startTime: 1,
+        runnable: true,
+        livePorts: 2,
+        pauseOnExit: false,
+        pauseEvent: Event(
+          kind: EventKind.kResume,
+          timestamp: 3,
+        ),
+        libraries: [],
+        breakpoints: [],
+      );
       var request = rpcRequest("setVMTimelineFlags", params: {
         'isolateId': isolate.id,
         // Note: the dynamic list below is intentional in order to exercise the
@@ -100,7 +106,7 @@
       test('with no params or isolateId', () {
         var extension = 'ext.cool';
         var request = rpcRequest(extension, params: null);
-        var response = Response()..json = {"hello": "world"};
+        var response = Response(type: '')..json = {"hello": "world"};
         when(serviceMock.callServiceExtension(
           extension,
           isolateId: argThat(isNull, named: 'isolateId'),
@@ -117,7 +123,7 @@
       test('with isolateId and no other params', () {
         var extension = 'ext.cool';
         var request = rpcRequest(extension, params: {'isolateId': '1'});
-        var response = Response()..json = {"hello": "world"};
+        var response = Response(type: '')..json = {"hello": "world"};
         when(serviceMock.callServiceExtension(
           extension,
           isolateId: argThat(equals('1'), named: 'isolateId'),
@@ -135,7 +141,7 @@
         var extension = 'ext.cool';
         var params = {'cool': 'option'};
         var request = rpcRequest(extension, params: params);
-        var response = Response()..json = {"hello": "world"};
+        var response = Response(type: '')..json = {"hello": "world"};
         when(serviceMock.callServiceExtension(
           extension,
           isolateId: argThat(isNull, named: 'isolateId'),
@@ -154,7 +160,7 @@
         var params = {'cool': 'option'};
         var request =
             rpcRequest(extension, params: Map.of(params)..['isolateId'] = '1');
-        var response = Response()..json = {"hello": "world"};
+        var response = Response(type: '')..json = {"hello": "world"};
         when(serviceMock.callServiceExtension(
           extension,
           isolateId: argThat(equals("1"), named: 'isolateId'),
@@ -209,12 +215,14 @@
         eventController = serviceMock.streamControllers[streamId];
 
         var events = [
-          Event()
-            ..kind = EventKind.kIsolateStart
-            ..timestamp = 0,
-          Event()
-            ..kind = EventKind.kIsolateExit
-            ..timestamp = 1,
+          Event(
+            kind: EventKind.kIsolateStart,
+            timestamp: 0,
+          ),
+          Event(
+            kind: EventKind.kIsolateExit,
+            timestamp: 1,
+          )
         ];
         events.forEach(eventController.add);
         await expect(
@@ -231,9 +239,10 @@
         requestsController.add(request);
         await expect(responseQueue, emitsThrough(rpcResponse(response)));
 
-        var nextEvent = Event()
-          ..kind = EventKind.kIsolateReload
-          ..timestamp = 2;
+        var nextEvent = Event(
+          kind: EventKind.kIsolateReload,
+          timestamp: 2,
+        );
         eventController.add(nextEvent);
         expect(responseQueue,
             neverEmits(streamNotifyResponse(streamId, nextEvent)));
@@ -294,24 +303,32 @@
       test('gives register and unregister events', () async {
         var serviceId = 'ext.test.service';
         var serviceRegisteredEvent = streamNotifyResponse(
-            serviceStream,
-            Event()
-              ..kind = EventKind.kServiceRegistered
-              ..method = serviceId
-              ..service = serviceId);
+          serviceStream,
+          Event(
+            kind: EventKind.kServiceRegistered,
+            timestamp: 0,
+            method: serviceId,
+            service: serviceId,
+          ),
+        );
         var serviceUnRegisteredEvent = streamNotifyResponse(
-            serviceStream,
-            Event()
-              ..kind = EventKind.kServiceUnregistered
-              ..method = serviceId
-              ..service = serviceId);
+          serviceStream,
+          Event(
+            kind: EventKind.kServiceUnregistered,
+            timestamp: 0,
+            method: serviceId,
+            service: serviceId,
+          ),
+        );
 
         requestsController.add(
             rpcRequest('streamListen', params: {'streamId': serviceStream}));
         requestsController
             .add(rpcRequest('registerService', params: {'service': serviceId}));
         await expect(
-            responsesController.stream, emitsThrough(serviceRegisteredEvent));
+            responsesController.stream
+                .map((Map response) => stripEventTimestamp(response)),
+            emitsThrough(serviceRegisteredEvent));
 
         // Connect another client to get the previous register events and the
         // unregister event.
@@ -326,7 +343,8 @@
             responsesController2.sink, serviceRegistry, null);
 
         expect(
-            responsesController2.stream,
+            responsesController2.stream
+                .map((Map response) => stripEventTimestamp(response)),
             emitsThrough(emitsInOrder(
                 [serviceRegisteredEvent, serviceUnRegisteredEvent])));
 
@@ -380,7 +398,7 @@
           clientInputController.sink, serviceRegistry, serviceMock);
 
       var requestParams = {'foo': 'bar'};
-      var expectedResponse = Response()..json = {'zap': 'zip'};
+      var expectedResponse = Response(type: '')..json = {'zap': 'zip'};
       await client.registerService(serviceId, null);
       // Duplicate registrations should fail.
       expect(client.registerService(serviceId, null),
@@ -402,7 +420,7 @@
       // This should complete as well.
       await clientConnection.done;
 
-      var mockResponse = Response()..json = {'mock': 'response'};
+      var mockResponse = Response(type: '')..json = {'mock': 'response'};
       when(serviceMock.callServiceExtension(serviceId,
               args: argThat(equals(requestParams), named: 'args'),
               isolateId: argThat(isNull, named: 'isolateId')))
@@ -463,6 +481,14 @@
   };
 }
 
+Map<String, Object> stripEventTimestamp(Map response) {
+  if (response.containsKey('params') &&
+      response['params'].containsKey('event')) {
+    response['params']['event']['timestamp'] = 0;
+  }
+  return response;
+}
+
 class MockVmService extends Mock implements VmServiceInterface {
   final streamControllers = <String, StreamController<Event>>{};
 
diff --git a/pkg/vm_service/tool/dart/generate_dart.dart b/pkg/vm_service/tool/dart/generate_dart.dart
index 0a5f50f..58607c9 100644
--- a/pkg/vm_service/tool/dart/generate_dart.dart
+++ b/pkg/vm_service/tool/dart/generate_dart.dart
@@ -50,6 +50,8 @@
 import 'dart:convert' show base64, jsonDecode, jsonEncode, utf8;
 import 'dart:typed_data';
 
+import 'package:meta/meta.dart';
+
 import 'src/service_extension_registry.dart';
 
 export 'src/service_extension_registry.dart' show ServiceExtensionRegistry;
@@ -79,7 +81,7 @@
     } else if (args == null) {
       return _call(method, {'isolateId': isolateId});
     } else {
-      args = new Map.from(args);
+      args = Map.from(args);
       if (isolateId != null) {
         args['isolateId'] = isolateId;
       }
@@ -106,7 +108,7 @@
 
   Future<T> _call<T>(String method, [Map args]) {
     String id = '${++_id}';
-    Completer<T> completer = new Completer<T>();
+    Completer<T> completer = Completer<T>();
     _completers[id] = completer;
     _methodCalls[id] = method;
     Map m = {'id': id, 'method': method};
@@ -120,7 +122,7 @@
   /// Register a service for invocation.
   void registerServiceCallback(String service, ServiceCallback cb) {
     if (_services.containsKey(service)) {
-      throw new Exception('Service \'${service}\' already registered');
+      throw Exception('Service \'${service}\' already registered');
     }
     _services[service] = cb;
   }
@@ -131,8 +133,8 @@
     if (message is String) {
       _processMessageStr(message);
     } else if (message is List<int>) {
-      Uint8List list = new Uint8List.fromList(message);
-      _processMessageByteData(new ByteData.view(list.buffer));
+      Uint8List list = Uint8List.fromList(message);
+      _processMessageByteData(ByteData.view(list.buffer));
     } else if (message is ByteData) {
       _processMessageByteData(message);
     } else {
@@ -144,10 +146,10 @@
     int offset = 0;
     int metaSize = bytes.getUint32(offset + 4, Endian.big);
     offset += 8;
-    String meta = utf8.decode(new Uint8List.view(
+    String meta = utf8.decode(Uint8List.view(
         bytes.buffer, bytes.offsetInBytes + offset, metaSize));
     offset += metaSize;
-    ByteData data = new ByteData.view(bytes.buffer, bytes.offsetInBytes + offset,
+    ByteData data = ByteData.view(bytes.buffer, bytes.offsetInBytes + offset,
         bytes.lengthInBytes - offset);
     dynamic map = jsonDecode(meta);
     if (map != null && map['method'] == 'streamNotify') {
@@ -251,7 +253,7 @@
 
 class RPCError {
   static RPCError parse(String callingMethod, dynamic json) {
-    return new RPCError(callingMethod, json['code'], json['message'], json['data']);
+    return RPCError(callingMethod, json['code'], json['message'], json['data']);
   }
 
   final String callingMethod;
@@ -275,7 +277,7 @@
 /// An `ExtensionData` is an arbitrary map that can have any contents.
 class ExtensionData {
   static ExtensionData parse(Map json) =>
-      json == null ? null : new ExtensionData._fromJson(json);
+      json == null ? null : ExtensionData._fromJson(json);
 
   final Map data;
 
@@ -417,11 +419,11 @@
     if (docs != null) docs = docs.trim();
 
     if (definition.startsWith('class ')) {
-      types.add(new Type(this, name, definition, docs));
+      types.add(Type(this, name, definition, docs));
     } else if (name.substring(0, 1).toLowerCase() == name.substring(0, 1)) {
-      methods.add(new Method(name, definition, docs));
+      methods.add(Method(name, definition, docs));
     } else if (definition.startsWith('enum ')) {
-      enums.add(new Enum(name, definition, docs));
+      enums.add(Enum(name, definition, docs));
     } else {
       throw 'unexpected entity: ${name}, ${definition}';
     }
@@ -682,7 +684,7 @@
         } else if (method.startsWith('ext.')) {
           // Remaining methods with `ext.` are assumed to be registered via
           // dart:developer, which the service implementation handles.
-          var args = params == null ? null : new Map.of(params);
+          var args = params == null ? null : Map.of(params);
           var isolateId = args?.remove('isolateId');
           response = await _serviceImplementation.callServiceExtension(method,
               isolateId: isolateId, args: args);
@@ -740,17 +742,17 @@
     gen.writeStatement('Log _log;');
     gen.write('''
 
-StreamController<String> _onSend = new StreamController.broadcast(sync: true);
-StreamController<String> _onReceive = new StreamController.broadcast(sync: true);
+StreamController<String> _onSend = StreamController.broadcast(sync: true);
+StreamController<String> _onReceive = StreamController.broadcast(sync: true);
 
-final Completer _onDoneCompleter = new Completer();
+final Completer _onDoneCompleter = Completer();
 
 Map<String, StreamController<Event>> _eventControllers = {};
 
 StreamController<Event> _getEventController(String eventName) {
   StreamController<Event> controller = _eventControllers[eventName];
   if (controller == null) {
-    controller = new StreamController.broadcast();
+    controller = StreamController.broadcast();
     _eventControllers[eventName] = controller;
   }
   return controller;
@@ -765,7 +767,7 @@
 }) {
   _streamSub = inStream.listen(_processMessage, onDone: ()=> _onDoneCompleter.complete());
   _writeMessage = writeMessage;
-  _log = log == null ? new _NullLog() : log;
+  _log = log == null ? _NullLog() : log;
   _disposeHandler = disposeHandler;
   streamClosed?.then((_) {
     if (!_onDoneCompleter.isCompleted) {
@@ -973,7 +975,7 @@
         if (line.isEmpty) {
           inStreamDef = false;
         } else {
-          streamCategories.add(new StreamCategory(line));
+          streamCategories.add(StreamCategory(line));
         }
       }
     }
@@ -1024,11 +1026,11 @@
   final String name;
   final String docs;
 
-  MemberType returnType = new MemberType();
+  MemberType returnType = MemberType();
   List<MethodArg> args = [];
 
   Method(this.name, String definition, [this.docs]) {
-    _parse(new Tokenizer(definition).tokenize());
+    _parse(Tokenizer(definition).tokenize());
   }
 
   bool get hasArgs => args.isNotEmpty;
@@ -1117,9 +1119,7 @@
     gen.write(') ');
   }
 
-  void _parse(Token token) {
-    new MethodParser(token).parseInto(this);
-  }
+  void _parse(Token token) => MethodParser(token).parseInto(this);
 }
 
 class MemberType extends Member {
@@ -1139,7 +1139,7 @@
           parser.advance();
         }
         parser.consume(')');
-        TypeRef ref = new TypeRef('dynamic');
+        TypeRef ref = TypeRef('dynamic');
         while (parser.consume('[')) {
           parser.expect(']');
           ref.arrayDepth++;
@@ -1147,7 +1147,7 @@
         types.add(ref);
       } else {
         Token t = parser.expectName();
-        TypeRef ref = new TypeRef(_coerceRefType(t.text));
+        TypeRef ref = TypeRef(_coerceRefType(t.text));
         while (parser.consume('[')) {
           parser.expect(']');
           ref.arrayDepth++;
@@ -1236,8 +1236,6 @@
 
   MethodArg(this.parent, this.type, this.name);
 
-  // String get paramType => type;
-
   void generate(DartGenerator gen) {
     gen.write('${type.ref} ${name}');
   }
@@ -1254,7 +1252,7 @@
   List<TypeField> fields = [];
 
   Type(this.parent, String categoryName, String definition, [this.docs]) {
-    _parse(new Tokenizer(definition).tokenize());
+    _parse(Tokenizer(definition).tokenize());
   }
 
   Type._(this.parent, this.rawName, this.name, this.superName, this.docs);
@@ -1276,7 +1274,7 @@
 
     final fields = map.values.toList().reversed.toList();
 
-    return new Type._(parent, rawName, name, superName, docs)..fields = fields;
+    return Type._(parent, rawName, name, superName, docs)..fields = fields;
   }
 
   bool get isResponse {
@@ -1318,7 +1316,7 @@
     if (superName != null) gen.write('extends ${superName} ');
     gen.writeln('{');
     gen.writeln('static ${name} parse(Map<String, dynamic> json) => '
-        'json == null ? null : new ${name}._fromJson(json);');
+        'json == null ? null : ${name}._fromJson(json);');
     gen.writeln();
 
     if (name == 'Response') {
@@ -1330,9 +1328,22 @@
     gen.writeln();
 
     // ctors
-    gen.writeln('${name}();');
-    gen.writeln();
 
+    // Default
+    gen.write('${name}(');
+    if (fields.isNotEmpty) {
+      gen.write('{');
+      fields
+          .where((field) => !field.optional)
+          .forEach((field) => field.generateNamedParameter(gen));
+      fields
+          .where((field) => field.optional)
+          .forEach((field) => field.generateNamedParameter(gen));
+      gen.write('}');
+    }
+    gen.writeln(');');
+
+    // Build from JSON.
     String superCall = superName == null ? '' : ": super._fromJson(json) ";
     if (name == 'Response') {
       gen.write('${name}._fromJson(this.json)');
@@ -1372,19 +1383,19 @@
       } else if (name == 'Instance' && field.name == 'associations') {
         // Special case `Instance.associations`.
         gen.writeln("associations = json['associations'] == null "
-            "? null : new List<MapAssociation>.from("
+            "? null : List<MapAssociation>.from("
             "_createSpecificObject(json['associations'], MapAssociation.parse));");
       } else if (name == '_CpuProfile' && field.name == 'codes') {
         // Special case `_CpuProfile.codes`.
-        gen.writeln("codes = new List<CodeRegion>.from("
+        gen.writeln("codes = List<CodeRegion>.from("
             "_createSpecificObject(json['codes'], CodeRegion.parse));");
       } else if (name == '_CpuProfile' && field.name == 'functions') {
         // Special case `_CpuProfile.functions`.
-        gen.writeln("functions = new List<ProfileFunction>.from("
+        gen.writeln("functions = List<ProfileFunction>.from("
             "_createSpecificObject(json['functions'], ProfileFunction.parse));");
       } else if (name == 'SourceReport' && field.name == 'ranges') {
         // Special case `SourceReport.ranges`.
-        gen.writeln("ranges = new List<SourceReportRange>.from("
+        gen.writeln("ranges = List<SourceReportRange>.from("
             "_createSpecificObject(json['ranges'], SourceReportRange.parse));");
       } else if (name == 'SourceReportRange' && field.name == 'coverage') {
         // Special case `SourceReportRange.coverage`.
@@ -1392,7 +1403,7 @@
             "json['coverage'], SourceReportCoverage.parse);");
       } else if (name == 'Library' && field.name == 'dependencies') {
         // Special case `Library.dependencies`.
-        gen.writeln("dependencies = new List<LibraryDependency>.from("
+        gen.writeln("dependencies = List<LibraryDependency>.from("
             "_createSpecificObject(json['dependencies'], "
             "LibraryDependency.parse));");
       } else if (name == 'Script' && field.name == 'tokenPosTable') {
@@ -1401,8 +1412,8 @@
         if (field.optional) {
           gen.write("json['tokenPosTable'] == null ? null : ");
         }
-        gen.writeln("new List<List<int>>.from(json['tokenPosTable'].map"
-            "((dynamic list) => new List<int>.from(list)));");
+        gen.writeln("List<List<int>>.from(json['tokenPosTable'].map"
+            "((dynamic list) => List<int>.from(list)));");
       } else if (field.type.isArray) {
         TypeRef fieldType = field.type.types.first;
         String typesList = _typeRefListToString(field.type.types);
@@ -1410,10 +1421,10 @@
         if (field.optional) {
           if (fieldType.isListTypeSimple) {
             gen.writeln("${field.generatableName} = $ref == null ? null : "
-                "new List<${fieldType.listTypeArg}>.from($ref);");
+                "List<${fieldType.listTypeArg}>.from($ref);");
           } else {
             gen.writeln("${field.generatableName} = $ref == null ? null : "
-                "new List<${fieldType.listTypeArg}>.from(createServiceObject($ref, $typesList));");
+                "List<${fieldType.listTypeArg}>.from(createServiceObject($ref, $typesList));");
           }
         } else {
           if (fieldType.isListTypeSimple) {
@@ -1421,20 +1432,20 @@
             // `new` and `old`. Post 3.18, these will be null.
             if (name == 'ClassHeapStats') {
               gen.writeln("${field.generatableName} = $ref == null ? null : "
-                  "new List<${fieldType.listTypeArg}>.from($ref);");
+                  "List<${fieldType.listTypeArg}>.from($ref);");
             } else {
               gen.writeln("${field.generatableName} = "
-                  "new List<${fieldType.listTypeArg}>.from($ref);");
+                  "List<${fieldType.listTypeArg}>.from($ref);");
             }
           } else {
             // Special case `InstanceSet`. Pre 3.20, instances were sent in a
             // field named 'samples' instead of 'instances'.
             if (name == 'InstanceSet') {
               gen.writeln("${field.generatableName} = "
-                  "new List<${fieldType.listTypeArg}>.from(createServiceObject($ref ?? json['samples'], $typesList));");
+                  "List<${fieldType.listTypeArg}>.from(createServiceObject($ref ?? json['samples'], $typesList));");
             } else {
               gen.writeln("${field.generatableName} = "
-                  "new List<${fieldType.listTypeArg}>.from(createServiceObject($ref, $typesList));");
+                  "List<${fieldType.listTypeArg}>.from(createServiceObject($ref, $typesList));");
             }
           }
         }
@@ -1615,9 +1626,7 @@
     gen.writeln('');
   }
 
-  void _parse(Token token) {
-    new TypeParser(token).parseInto(this);
-  }
+  void _parse(Token token) => TypeParser(token).parseInto(this);
 
   void calculateFieldOverrides() {
     for (TypeField field in fields.toList()) {
@@ -1648,7 +1657,7 @@
 
   final Type parent;
   final String _docs;
-  MemberType type = new MemberType();
+  MemberType type = MemberType();
   String name;
   bool optional = false;
   String defaultValue;
@@ -1656,9 +1665,7 @@
 
   TypeField(this.parent, this._docs);
 
-  void setOverrides() {
-    overrides = true;
-  }
+  void setOverrides() => overrides = true;
 
   String get docs {
     String str = _docs == null ? '' : _docs;
@@ -1683,6 +1690,13 @@
     gen.writeStatement('${typeName} ${generatableName};');
     if (parent.fields.any((field) => field.hasDocs)) gen.writeln();
   }
+
+  void generateNamedParameter(DartGenerator gen) {
+    if (!optional) {
+      gen.write('@required ');
+    }
+    gen.writeStatement('this.${generatableName},');
+  }
 }
 
 class Enum extends Member {
@@ -1692,7 +1706,7 @@
   List<EnumValue> enums = [];
 
   Enum(this.name, String definition, [this.docs]) {
-    _parse(new Tokenizer(definition).tokenize());
+    _parse(Tokenizer(definition).tokenize());
   }
 
   Enum._(this.name, this.docs);
@@ -1711,7 +1725,7 @@
 
     final enums = map.values.toList().reversed.toList();
 
-    return new Enum._(name, docs)..enums = enums;
+    return Enum._(name, docs)..enums = enums;
   }
 
   String get prefix =>
@@ -1739,9 +1753,7 @@
     gen.writeln('');
   }
 
-  void _parse(Token token) {
-    new EnumParser(token).parseInto(this);
-  }
+  void _parse(Token token) => EnumParser(token).parseInto(this);
 }
 
 class EnumValue extends Member {
@@ -1761,12 +1773,12 @@
 
 class TextOutputVisitor implements NodeVisitor {
   static String printText(Node node) {
-    TextOutputVisitor visitor = new TextOutputVisitor();
+    TextOutputVisitor visitor = TextOutputVisitor();
     node.accept(visitor);
     return visitor.toString();
   }
 
-  StringBuffer buf = new StringBuffer();
+  StringBuffer buf = StringBuffer();
   bool _em = false;
   bool _href = false;
   bool _blockquote = false;
@@ -1845,7 +1857,7 @@
 
     while (peek().text != ')') {
       Token type = expectName();
-      TypeRef ref = new TypeRef(_coerceRefType(type.text));
+      TypeRef ref = TypeRef(_coerceRefType(type.text));
       if (peek().text == '[') {
         while (consume('[')) {
           expect(']');
@@ -1857,15 +1869,14 @@
         ref.genericTypes = [];
         while (peek().text != '>') {
           Token genericTypeName = expectName();
-          ref.genericTypes
-              .add(new TypeRef(_coerceRefType(genericTypeName.text)));
+          ref.genericTypes.add(TypeRef(_coerceRefType(genericTypeName.text)));
           consume(',');
         }
         expect('>');
       }
 
       Token name = expectName();
-      MethodArg arg = new MethodArg(method, ref, name.text);
+      MethodArg arg = MethodArg(method, ref, name.text);
       if (consume('[')) {
         expect('optional');
         expect(']');
@@ -1906,7 +1917,7 @@
     expect('{');
 
     while (peek().text != '}') {
-      TypeField field = new TypeField(type, collectComments());
+      TypeField field = TypeField(type, collectComments());
       field.type.parse(this);
       field.name = expectName().text;
       if (consume('[')) {
@@ -1940,7 +1951,7 @@
       t = expectName();
       consume(',');
 
-      e.enums.add(new EnumValue(e, t.text, docs));
+      e.enums.add(EnumValue(e, t.text, docs));
     }
   }
 }
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index 529da63..a3cc367 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -240,6 +240,10 @@
     "third_party/double-conversion/src:libdouble_conversion",
     ":generate_version_cc_file",
   ]
+  if (dart_enable_wasm) {
+    extra_deps += [ "//third_party/wasmer" ]
+    defines = [ "DART_ENABLE_WASM" ]
+  }
   if (is_fuchsia) {
     if (using_fuchsia_sdk) {
       extra_deps += [ "$fuchsia_sdk_root/pkg:fdio" ]
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index dd9ea2c..4f60c40 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -266,12 +266,15 @@
 
     if (is_fuchsia) {
       if (using_fuchsia_sdk) {
-        deps += [ "$fuchsia_sdk_root/pkg/lib/netstack/c" ]
+        deps += [
+          "$fuchsia_sdk_root/fidl:fuchsia.netstack",
+          "$fuchsia_sdk_root/pkg:sys_cpp",
+        ]
         public_deps = [
           "$fuchsia_sdk_root/pkg:fdio",
         ]
       } else {
-        deps += [ "//garnet/public/lib/netstack/c" ]
+        deps += [ "//sdk/fidl/fuchsia.netstack" ]
         public_deps = [
           "//zircon/public/lib/fdio",
         ]
@@ -388,12 +391,15 @@
 
     if (is_fuchsia) {
       if (using_fuchsia_sdk) {
-        deps += [ "$fuchsia_sdk_root/pkg/lib/netstack/c" ]
+        deps += [
+          "$fuchsia_sdk_root/fidl:fuchsia.netstack",
+          "$fuchsia_sdk_root/pkg:sys_cpp",
+        ]
         public_deps = [
           "$fuchsia_sdk_root/pkg:fdio",
         ]
       } else {
-        deps += [ "//garnet/public/lib/netstack/c" ]
+        deps += [ "//sdk/fidl/fuchsia.netstack" ]
         public_deps = [
           "//zircon/public/lib/fdio",
         ]
diff --git a/runtime/bin/builtin_sources.gni b/runtime/bin/builtin_sources.gni
index c9edd40..8ed3c7d 100644
--- a/runtime/bin/builtin_sources.gni
+++ b/runtime/bin/builtin_sources.gni
@@ -1,6 +1,3 @@
 # 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.
-
-# This file contains all dart sources for the dart:_builtin library.
-builtin_sources = [ "builtin.dart" ]
diff --git a/runtime/bin/cli_sources.gni b/runtime/bin/cli_sources.gni
index ed72a04..cb2e6d6 100644
--- a/runtime/bin/cli_sources.gni
+++ b/runtime/bin/cli_sources.gni
@@ -2,5 +2,3 @@
 # for 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 contains all sources for the dart:cli library.
-cli_runtime_dart_files = [ "cli_patch.dart" ]
diff --git a/runtime/bin/dart_embedder_api_impl.cc b/runtime/bin/dart_embedder_api_impl.cc
index cf2116a..a7fde47 100644
--- a/runtime/bin/dart_embedder_api_impl.cc
+++ b/runtime/bin/dart_embedder_api_impl.cc
@@ -88,8 +88,9 @@
   Dart_EnterScope();
   // Load embedder specific bits and return.
   if (!bin::VmService::Setup(config.ip, config.port, config.dev_mode,
-                             config.disable_auth_codes, /*trace_loading=*/false,
-                             config.deterministic)) {
+                             config.disable_auth_codes,
+                             config.write_service_info_filename,
+                             /*trace_loading=*/false, config.deterministic)) {
     *error = strdup(bin::VmService::GetErrorMessage());
     return nullptr;
   }
diff --git a/runtime/bin/dfe.cc b/runtime/bin/dfe.cc
index 3e5eaf9..761c536 100644
--- a/runtime/bin/dfe.cc
+++ b/runtime/bin/dfe.cc
@@ -42,11 +42,23 @@
 const char kSnapshotsDirectory[] = "snapshots";
 
 static char* GetDirectoryPrefixFromExeName() {
-  const char* name = Platform::GetExecutableName();
+  const char* name = nullptr;
+  const int kTargetSize = 4096;
+  char target[kTargetSize];
+  intptr_t target_size =
+      Platform::ResolveExecutablePathInto(target, kTargetSize);
+  if (target_size > 0 && target_size < kTargetSize - 1) {
+    target[target_size] = 0;
+    name = target;
+  }
+  if (name == nullptr) {
+    name = Platform::GetExecutableName();
+    target_size = strlen(name);
+  }
   const char* sep = File::PathSeparator();
   const intptr_t sep_length = strlen(sep);
 
-  for (intptr_t i = strlen(name) - 1; i >= 0; --i) {
+  for (intptr_t i = target_size - 1; i >= 0; --i) {
     const char* str = name + i;
     if (strncmp(str, sep, sep_length) == 0
 #if defined(HOST_OS_WINDOWS)
diff --git a/runtime/bin/file.h b/runtime/bin/file.h
index a3347c0..928fbdd 100644
--- a/runtime/bin/file.h
+++ b/runtime/bin/file.h
@@ -223,6 +223,9 @@
   static const char* GetCanonicalPath(Namespace* namespc, const char* path);
   // Link LinkTarget, but pathname must be absolute.
   static const char* ReadLink(const char* pathname);
+  static intptr_t ReadLinkInto(const char* pathname,
+                               char* result,
+                               size_t result_size);
 
   // Cleans an input path, transforming it to out, according to the rules
   // defined by "Lexical File Names in Plan 9 or Getting Dot-Dot Right",
diff --git a/runtime/bin/file_android.cc b/runtime/bin/file_android.cc
index ef983f3..c634b0d 100644
--- a/runtime/bin/file_android.cc
+++ b/runtime/bin/file_android.cc
@@ -579,24 +579,34 @@
   return ((pathname != NULL) && (pathname[0] == '/'));
 }
 
-const char* File::ReadLink(const char* pathname) {
+intptr_t File::ReadLinkInto(const char* pathname,
+                            char* result,
+                            size_t result_size) {
   ASSERT(pathname != NULL);
   ASSERT(IsAbsolutePath(pathname));
   struct stat link_stats;
   if (TEMP_FAILURE_RETRY(lstat(pathname, &link_stats)) != 0) {
-    return NULL;
+    return -1;
   }
   if (!S_ISLNK(link_stats.st_mode)) {
     errno = ENOENT;
-    return NULL;
+    return -1;
   }
+  const size_t target_size =
+      TEMP_FAILURE_RETRY(readlink(pathname, result, result_size));
+  if (target_size <= 0) {
+    return -1;
+  }
+  return target_size;
+}
+
+const char* File::ReadLink(const char* pathname) {
   // Don't rely on the link_stats.st_size for the size of the link
   // target. For some filesystems, e.g. procfs, this value is always
   // 0. Also the link might have changed before the readlink call.
   const int kBufferSize = PATH_MAX + 1;
   char target[kBufferSize];
-  size_t target_size =
-      TEMP_FAILURE_RETRY(readlink(pathname, target, kBufferSize));
+  size_t target_size = ReadLinkInto(pathname, target, kBufferSize);
   if (target_size <= 0) {
     return NULL;
   }
diff --git a/runtime/bin/file_linux.cc b/runtime/bin/file_linux.cc
index f53d69a..e6db3ad 100644
--- a/runtime/bin/file_linux.cc
+++ b/runtime/bin/file_linux.cc
@@ -572,24 +572,34 @@
   return (pathname != NULL) && (pathname[0] == '/');
 }
 
-const char* File::ReadLink(const char* pathname) {
+intptr_t File::ReadLinkInto(const char* pathname,
+                            char* result,
+                            size_t result_size) {
   ASSERT(pathname != NULL);
   ASSERT(IsAbsolutePath(pathname));
   struct stat64 link_stats;
   if (TEMP_FAILURE_RETRY(lstat64(pathname, &link_stats)) != 0) {
-    return NULL;
+    return -1;
   }
   if (!S_ISLNK(link_stats.st_mode)) {
     errno = ENOENT;
-    return NULL;
+    return -1;
   }
+  const size_t target_size =
+      TEMP_FAILURE_RETRY(readlink(pathname, result, result_size));
+  if (target_size <= 0) {
+    return -1;
+  }
+  return target_size;
+}
+
+const char* File::ReadLink(const char* pathname) {
   // Don't rely on the link_stats.st_size for the size of the link
   // target. For some filesystems, e.g. procfs, this value is always
   // 0. Also the link might have changed before the readlink call.
   const int kBufferSize = PATH_MAX + 1;
   char target[kBufferSize];
-  size_t target_size =
-      TEMP_FAILURE_RETRY(readlink(pathname, target, kBufferSize));
+  size_t target_size = ReadLinkInto(pathname, target, kBufferSize);
   if (target_size <= 0) {
     return NULL;
   }
diff --git a/runtime/bin/io_sources.gni b/runtime/bin/io_sources.gni
index 56de0e7..8ed3c7d 100644
--- a/runtime/bin/io_sources.gni
+++ b/runtime/bin/io_sources.gni
@@ -1,21 +1,3 @@
 # 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.
-
-# This file contains all sources for the dart:io library.
-io_runtime_dart_files = [
-  "common_patch.dart",
-  "directory_patch.dart",
-  "eventhandler_patch.dart",
-  "file_patch.dart",
-  "file_system_entity_patch.dart",
-  "filter_patch.dart",
-  "io_service_patch.dart",
-  "namespace_patch.dart",
-  "platform_patch.dart",
-  "process_patch.dart",
-  "socket_patch.dart",
-  "stdio_patch.dart",
-  "secure_socket_patch.dart",
-  "sync_socket_patch.dart",
-]
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 2ff8888..483368c 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -597,7 +597,8 @@
   if (!VmService::Setup(
           Options::vm_service_server_ip(), Options::vm_service_server_port(),
           Options::vm_service_dev_mode(), Options::vm_service_auth_disabled(),
-          Options::trace_loading(), Options::deterministic())) {
+          Options::vm_write_service_info_filename(), Options::trace_loading(),
+          Options::deterministic())) {
     *error = strdup(VmService::GetErrorMessage());
     return NULL;
   }
@@ -1081,29 +1082,48 @@
   }
   vm_options.AddArgument("--new_gen_growth_factor=4");
 
-  // Parse command line arguments.
-  if (Options::ParseArguments(argc, argv, vm_run_app_snapshot, &vm_options,
-                              &script_name, &dart_options, &print_flags_seen,
-                              &verbose_debug_seen) < 0) {
-    if (Options::help_option()) {
-      Options::PrintUsage();
-      Platform::Exit(0);
-    } else if (Options::version_option()) {
-      Options::PrintVersion();
-      Platform::Exit(0);
-    } else if (print_flags_seen) {
-      // Will set the VM flags, print them out and then we exit as no
-      // script was specified on the command line.
-      char* error = Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
-      if (error != NULL) {
-        Syslog::PrintErr("Setting VM flags failed: %s\n", error);
-        free(error);
+  // If the executable binary contains the runtime together with an appended
+  // snapshot, load and run that.
+  // Any arguments passed to such an executable are meant for the actual
+  // application so skip all Dart VM flag parsing.
+  AppSnapshot* app_snapshot =
+      Snapshot::TryReadAppendedAppSnapshotBlobs(argv[0]);
+  if (app_snapshot != nullptr) {
+    script_name = argv[0];
+
+    // Store the executable name.
+    Platform::SetExecutableName(argv[0]);
+
+    // Parse out options to be passed to dart main.
+    for (int i = 1; i < argc; i++) {
+      dart_options.AddArgument(argv[i]);
+    }
+  } else {
+    // Parse command line arguments.
+    if (Options::ParseArguments(argc, argv, vm_run_app_snapshot, &vm_options,
+                                &script_name, &dart_options, &print_flags_seen,
+                                &verbose_debug_seen) < 0) {
+      if (Options::help_option()) {
+        Options::PrintUsage();
+        Platform::Exit(0);
+      } else if (Options::version_option()) {
+        Options::PrintVersion();
+        Platform::Exit(0);
+      } else if (print_flags_seen) {
+        // Will set the VM flags, print them out and then we exit as no
+        // script was specified on the command line.
+        char* error =
+            Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
+        if (error != NULL) {
+          Syslog::PrintErr("Setting VM flags failed: %s\n", error);
+          free(error);
+          Platform::Exit(kErrorExitCode);
+        }
+        Platform::Exit(0);
+      } else {
+        Options::PrintUsage();
         Platform::Exit(kErrorExitCode);
       }
-      Platform::Exit(0);
-    } else {
-      Options::PrintUsage();
-      Platform::Exit(kErrorExitCode);
     }
   }
   DartUtils::SetEnvironment(Options::environment());
@@ -1131,8 +1151,10 @@
     shared_blobs->SetBuffers(&ignored, &ignored, &app_isolate_shared_data,
                              &app_isolate_shared_instructions);
   }
-  AppSnapshot* app_snapshot = Snapshot::TryReadAppSnapshot(script_name);
-  if (app_snapshot != NULL) {
+  if (app_snapshot == nullptr) {
+    app_snapshot = Snapshot::TryReadAppSnapshot(script_name);
+  }
+  if (app_snapshot != nullptr) {
     vm_run_app_snapshot = true;
     app_snapshot->SetBuffers(&vm_snapshot_data, &vm_snapshot_instructions,
                              &app_isolate_snapshot_data,
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index ee4516e..38c26d7 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -147,6 +147,10 @@
 "      --warn-on-pause-with-no-debugger\n"
 "  This set is subject to change.\n"
 "  Please see these options (--help --verbose) for further documentation.\n"
+"--write-service-info=<file_name>\n"
+"  Outputs information necessary to connect to the VM service to the\n"
+"  specified file in JSON format. Useful for clients which are unable to\n"
+"  listen to stdout for the Observatory listening message.\n"
 "--snapshot-kind=<snapshot_kind>\n"
 "--snapshot=<file_name>\n"
 "  These snapshot options are used to generate a snapshot of the loaded\n"
@@ -178,6 +182,10 @@
 "      --warn-on-pause-with-no-debugger\n"
 "  This set is subject to change.\n"
 "  Please see these options for further documentation.\n"
+"--write-service-info=<file_name>\n"
+"  Outputs information necessary to connect to the VM service to the\n"
+"  specified file in JSON format. Useful for clients which are unable to\n"
+"  listen to stdout for the Observatory listening message.\n"
 "--snapshot-kind=<snapshot_kind>\n"
 "--snapshot=<file_name>\n"
 "  These snapshot options are used to generate a snapshot of the loaded\n"
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index 8513fe3..32c6d9c 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -30,7 +30,8 @@
   V(load_type_feedback, load_type_feedback_filename)                           \
   V(root_certs_file, root_certs_file)                                          \
   V(root_certs_cache, root_certs_cache)                                        \
-  V(namespace, namespc)
+  V(namespace, namespc)                                                        \
+  V(write_service_info, vm_write_service_info_filename)
 
 // As STRING_OPTIONS_LIST but for boolean valued options. The default value is
 // always false, and the presence of the flag switches the value to true.
diff --git a/runtime/bin/platform.h b/runtime/bin/platform.h
index 30d92ae7..b0b3aa2 100644
--- a/runtime/bin/platform.h
+++ b/runtime/bin/platform.h
@@ -64,6 +64,15 @@
 
   static const char* ResolveExecutablePath();
 
+  // On Linux and Android this has the same effect as calling
+  // ResolveExecutablePath except that Dart_ScopeAllocate is not called and that
+  // the result goes into the given parameters.
+  // On all other platforms it returns -1, i.e. doesn't work.
+  // Note that `result` should be pre-allocated with size `result_size`.
+  // The return-value is the length read into `result` or -1 on failure.
+  // The content of `result` is not guranteed to be null-terminated.
+  static intptr_t ResolveExecutablePathInto(char* result, size_t result_size);
+
   // Stores the executable name.
   static void SetExecutableName(const char* executable_name) {
     executable_name_ = executable_name;
diff --git a/runtime/bin/platform_android.cc b/runtime/bin/platform_android.cc
index 5fa361f..6555965 100644
--- a/runtime/bin/platform_android.cc
+++ b/runtime/bin/platform_android.cc
@@ -155,6 +155,10 @@
   return File::ReadLink("/proc/self/exe");
 }
 
+intptr_t Platform::ResolveExecutablePathInto(char* result, size_t result_size) {
+  return File::ReadLinkInto("/proc/self/exe", result, result_size);
+}
+
 void Platform::Exit(int exit_code) {
   Console::RestoreConfig();
   Dart_PrepareToAbort();
diff --git a/runtime/bin/platform_fuchsia.cc b/runtime/bin/platform_fuchsia.cc
index 3f4d7a0..3fa55be 100644
--- a/runtime/bin/platform_fuchsia.cc
+++ b/runtime/bin/platform_fuchsia.cc
@@ -147,6 +147,10 @@
   return NULL;
 }
 
+intptr_t Platform::ResolveExecutablePathInto(char* result, size_t result_size) {
+  return -1;
+}
+
 void Platform::Exit(int exit_code) {
   Console::RestoreConfig();
   Dart_PrepareToAbort();
diff --git a/runtime/bin/platform_linux.cc b/runtime/bin/platform_linux.cc
index b0fc285..e6571af 100644
--- a/runtime/bin/platform_linux.cc
+++ b/runtime/bin/platform_linux.cc
@@ -162,6 +162,10 @@
   return File::ReadLink("/proc/self/exe");
 }
 
+intptr_t Platform::ResolveExecutablePathInto(char* result, size_t result_size) {
+  return File::ReadLinkInto("/proc/self/exe", result, result_size);
+}
+
 void Platform::Exit(int exit_code) {
   Console::RestoreConfig();
   Dart_PrepareToAbort();
diff --git a/runtime/bin/platform_macos.cc b/runtime/bin/platform_macos.cc
index 79ff679..2be3f30 100644
--- a/runtime/bin/platform_macos.cc
+++ b/runtime/bin/platform_macos.cc
@@ -251,6 +251,10 @@
   return canon_path;
 }
 
+intptr_t Platform::ResolveExecutablePathInto(char* result, size_t result_size) {
+  return -1;
+}
+
 void Platform::Exit(int exit_code) {
   Console::RestoreConfig();
   Dart_PrepareToAbort();
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc
index c5820b8..e4f20a2 100644
--- a/runtime/bin/platform_win.cc
+++ b/runtime/bin/platform_win.cc
@@ -285,6 +285,10 @@
   return canon_path;
 }
 
+intptr_t Platform::ResolveExecutablePathInto(char* result, size_t result_size) {
+  return -1;
+}
+
 void Platform::Exit(int exit_code) {
   // Restore the console's output code page
   Console::RestoreConfig();
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index 694577e..24626af 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -151,6 +151,7 @@
   // Load embedder specific bits and return.
   if (!bin::VmService::Setup("127.0.0.1", 0,
                              /*dev_mode=*/false, /*auth_disabled=*/true,
+                             /*write_service_info_filename*/ "",
                              /*trace_loading=*/false, /*deterministic=*/true)) {
     *error = strdup(bin::VmService::GetErrorMessage());
     return nullptr;
diff --git a/runtime/bin/snapshot_utils.cc b/runtime/bin/snapshot_utils.cc
index 58407ce..673e556 100644
--- a/runtime/bin/snapshot_utils.cc
+++ b/runtime/bin/snapshot_utils.cc
@@ -75,24 +75,21 @@
   MappedMemory* isolate_instructions_mapping_;
 };
 
-static AppSnapshot* TryReadAppSnapshotBlobs(const char* script_name) {
-  File* file = File::Open(NULL, script_name, File::kRead);
-  if (file == NULL) {
-    return NULL;
+static AppSnapshot* TryReadAppSnapshotBlobs(const char* script_name,
+                                            File* file) {
+  if ((file->Length() - file->Position()) < kAppSnapshotHeaderSize) {
+    return nullptr;
   }
-  RefCntReleaseScope<File> rs(file);
-  if (file->Length() < kAppSnapshotHeaderSize) {
-    return NULL;
-  }
+
   int64_t header[5];
   ASSERT(sizeof(header) == kAppSnapshotHeaderSize);
   if (!file->ReadFully(&header, kAppSnapshotHeaderSize)) {
-    return NULL;
+    return nullptr;
   }
   ASSERT(sizeof(header[0]) == appjit_magic_number.length);
   if (memcmp(&header[0], appjit_magic_number.bytes,
              appjit_magic_number.length) != 0) {
-    return NULL;
+    return nullptr;
   }
 
   int64_t vm_data_size = header[1];
@@ -115,39 +112,39 @@
         Utils::RoundUp(isolate_instructions_position, kAppSnapshotPageSize);
   }
 
-  MappedMemory* vm_data_mapping = NULL;
+  MappedMemory* vm_data_mapping = nullptr;
   if (vm_data_size != 0) {
     vm_data_mapping =
         file->Map(File::kReadOnly, vm_data_position, vm_data_size);
-    if (vm_data_mapping == NULL) {
+    if (vm_data_mapping == nullptr) {
       FATAL1("Failed to memory map snapshot: %s\n", script_name);
     }
   }
 
-  MappedMemory* vm_instr_mapping = NULL;
+  MappedMemory* vm_instr_mapping = nullptr;
   if (vm_instructions_size != 0) {
     vm_instr_mapping = file->Map(File::kReadExecute, vm_instructions_position,
                                  vm_instructions_size);
-    if (vm_instr_mapping == NULL) {
+    if (vm_instr_mapping == nullptr) {
       FATAL1("Failed to memory map snapshot: %s\n", script_name);
     }
   }
 
-  MappedMemory* isolate_data_mapping = NULL;
+  MappedMemory* isolate_data_mapping = nullptr;
   if (isolate_data_size != 0) {
     isolate_data_mapping =
         file->Map(File::kReadOnly, isolate_data_position, isolate_data_size);
-    if (isolate_data_mapping == NULL) {
+    if (isolate_data_mapping == nullptr) {
       FATAL1("Failed to memory map snapshot: %s\n", script_name);
     }
   }
 
-  MappedMemory* isolate_instr_mapping = NULL;
+  MappedMemory* isolate_instr_mapping = nullptr;
   if (isolate_instructions_size != 0) {
     isolate_instr_mapping =
         file->Map(File::kReadExecute, isolate_instructions_position,
                   isolate_instructions_size);
-    if (isolate_instr_mapping == NULL) {
+    if (isolate_instr_mapping == nullptr) {
       FATAL1("Failed to memory map snapshot: %s\n", script_name);
     }
   }
@@ -156,6 +153,41 @@
                                isolate_data_mapping, isolate_instr_mapping);
 }
 
+static AppSnapshot* TryReadAppSnapshotBlobs(const char* script_name) {
+  File* file = File::Open(NULL, script_name, File::kRead);
+  if (file == nullptr) {
+    return nullptr;
+  }
+  RefCntReleaseScope<File> rs(file);
+  return TryReadAppSnapshotBlobs(script_name, file);
+}
+
+AppSnapshot* Snapshot::TryReadAppendedAppSnapshotBlobs(
+    const char* container_path) {
+  File* file = File::Open(NULL, container_path, File::kRead);
+  if (file == nullptr) {
+    return nullptr;
+  }
+  RefCntReleaseScope<File> rs(file);
+
+  // Check for payload appended at the end of the container file.
+  // If header is found, jump to payload offset.
+  int64_t appended_header[2];
+  if (!file->SetPosition(file->Length() - sizeof(appended_header))) {
+    return nullptr;
+  }
+  if (!file->ReadFully(&appended_header, sizeof(appended_header))) {
+    return nullptr;
+  }
+  if (memcmp(&appended_header[1], appjit_magic_number.bytes,
+             appjit_magic_number.length) != 0 ||
+      appended_header[0] <= 0 || !file->SetPosition(appended_header[0])) {
+    return nullptr;
+  }
+
+  return TryReadAppSnapshotBlobs(container_path, file);
+}
+
 #if defined(DART_PRECOMPILED_RUNTIME)
 class DylibAppSnapshot : public AppSnapshot {
  public:
diff --git a/runtime/bin/snapshot_utils.h b/runtime/bin/snapshot_utils.h
index 8f5bb1b..5b7cf82 100644
--- a/runtime/bin/snapshot_utils.h
+++ b/runtime/bin/snapshot_utils.h
@@ -37,6 +37,8 @@
                                     const uint8_t* shared_instructions);
   static void GenerateAppAOTAsAssembly(const char* snapshot_filename);
 
+  static AppSnapshot* TryReadAppendedAppSnapshotBlobs(
+      const char* container_path);
   static AppSnapshot* TryReadAppSnapshot(const char* script_name);
   static void WriteAppSnapshot(const char* filename,
                                uint8_t* vm_data_buffer,
diff --git a/runtime/bin/socket_base_fuchsia.cc b/runtime/bin/socket_base_fuchsia.cc
index a08257d..65a44805 100644
--- a/runtime/bin/socket_base_fuchsia.cc
+++ b/runtime/bin/socket_base_fuchsia.cc
@@ -7,20 +7,18 @@
 
 #include "bin/socket_base.h"
 
-// TODO(ZX-766): If/when Fuchsia adds getifaddrs(), use that instead of the
-// ioctl in netconfig.h.
-#include <errno.h>    // NOLINT
-#include <fcntl.h>    // NOLINT
-#include <ifaddrs.h>  // NOLINT
-#include <lib/netstack/c/netconfig.h>
-#include <net/if.h>       // NOLINT
-#include <netinet/tcp.h>  // NOLINT
-#include <stdio.h>        // NOLINT
-#include <stdlib.h>       // NOLINT
-#include <string.h>       // NOLINT
-#include <sys/ioctl.h>    // NOLINT
-#include <sys/stat.h>     // NOLINT
-#include <unistd.h>       // NOLINT
+#include <errno.h>
+#include <fuchsia/netstack/cpp/fidl.h>
+#include <ifaddrs.h>
+#include <lib/sys/cpp/service_directory.h>
+#include <net/if.h>
+#include <netinet/tcp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <vector>
 
 #include "bin/eventhandler.h"
 #include "bin/fdutils.h"
@@ -66,9 +64,20 @@
   memmove(reinterpret_cast<void*>(&addr_), sa, salen);
 }
 
+static fidl::SynchronousInterfacePtr<fuchsia::netstack::Netstack> netstack;
+static std::once_flag once;
+
 bool SocketBase::Initialize() {
-  // Nothing to do on Fuchsia.
-  return true;
+  static zx_status_t status;
+  std::call_once(once, [&]() {
+    auto directory = sys::ServiceDirectory::CreateFromNamespace();
+    status = directory->Connect(netstack.NewRequest());
+    if (status != ZX_OK) {
+      LOG_ERR("Initialize: connecting to fuchsia.netstack failed: %s\n",
+              zx_status_get_string(status));
+    }
+  });
+  return status == ZX_OK;
 }
 
 bool SocketBase::FormatNumericAddress(const RawAddr& addr,
@@ -264,13 +273,6 @@
   return (result == 1);
 }
 
-static bool ShouldIncludeIfaAddrs(netc_if_info_t* if_info, int lookup_family) {
-  const int family = if_info->addr.ss_family;
-  return ((lookup_family == family) ||
-          (((lookup_family == AF_UNSPEC) &&
-            ((family == AF_INET) || (family == AF_INET6)))));
-}
-
 bool SocketBase::ListInterfacesSupported() {
   return true;
 }
@@ -278,54 +280,59 @@
 AddressList<InterfaceSocketAddress>* SocketBase::ListInterfaces(
     int type,
     OSError** os_error) {
-  // We need a dummy socket.
-  const int fd = socket(AF_INET6, SOCK_STREAM, 0);
-  if (fd < 0) {
-    LOG_ERR("ListInterfaces: socket(AF_INET, SOCK_DGRAM, 0) failed\n");
+  std::vector<fuchsia::netstack::NetInterface2> interfaces;
+  zx_status_t status = netstack->GetInterfaces2(&interfaces);
+  if (status != ZX_OK) {
+    LOG_ERR("ListInterfaces: fuchsia.netstack.GetInterfaces2 failed: %s\n",
+            zx_status_get_string(status));
+    errno = EIO;
     return NULL;
   }
 
-  // Call the ioctls.
-  netc_get_if_info_t get_if_info;
-  const ssize_t size = ioctl_netc_get_num_ifs(fd, &get_if_info.n_info);
-  if (size < 0) {
-    LOG_ERR("ListInterfaces: ioctl_netc_get_num_ifs() failed");
-    close(fd);
-    return NULL;
-  }
-  for (uint32_t i = 0; i < get_if_info.n_info; i++) {
-    const ssize_t size =
-        ioctl_netc_get_if_info_at(fd, &i, &get_if_info.info[i]);
-    if (size < 0) {
-      LOG_ERR("ListInterfaces: ioctl_netc_get_if_info_at() failed");
-      close(fd);
-      return NULL;
-    }
-  }
-
   // Process the results.
   const int lookup_family = SocketAddress::FromType(type);
-  intptr_t count = 0;
-  for (intptr_t i = 0; i < get_if_info.n_info; i++) {
-    if (ShouldIncludeIfaAddrs(&get_if_info.info[i], lookup_family)) {
-      count++;
-    }
-  }
 
-  AddressList<InterfaceSocketAddress>* addresses =
-      new AddressList<InterfaceSocketAddress>(count);
+  std::remove_if(
+      interfaces.begin(), interfaces.end(),
+      [lookup_family](const auto& interface) {
+        switch (interface.addr.Which()) {
+          case fuchsia::net::IpAddress::Tag::kIpv4:
+            return !(lookup_family == AF_UNSPEC || lookup_family == AF_INET);
+          case fuchsia::net::IpAddress::Tag::kIpv6:
+            return !(lookup_family == AF_UNSPEC || lookup_family == AF_INET6);
+          case fuchsia::net::IpAddress::Tag::Invalid:
+            return true;
+        }
+      });
+
+  auto addresses = new AddressList<InterfaceSocketAddress>(interfaces.size());
   int addresses_idx = 0;
-  for (intptr_t i = 0; i < get_if_info.n_info; i++) {
-    if (ShouldIncludeIfaAddrs(&get_if_info.info[i], lookup_family)) {
-      char* ifa_name = DartUtils::ScopedCopyCString(get_if_info.info[i].name);
-      InterfaceSocketAddress* isa = new InterfaceSocketAddress(
-          reinterpret_cast<struct sockaddr*>(&get_if_info.info[i].addr),
-          ifa_name, if_nametoindex(get_if_info.info[i].name));
-      addresses->SetAt(addresses_idx, isa);
-      addresses_idx++;
+  for (const auto& interface : interfaces) {
+    struct sockaddr_storage addr = {};
+    auto addr_in = reinterpret_cast<struct sockaddr_in*>(&addr);
+    auto addr_in6 = reinterpret_cast<struct sockaddr_in6*>(&addr);
+    switch (interface.addr.Which()) {
+      case fuchsia::net::IpAddress::Tag::kIpv4:
+        addr_in->sin_family = AF_INET;
+        memmove(&addr_in->sin_addr, interface.addr.ipv4().addr.data(),
+                sizeof(addr_in->sin_addr));
+        break;
+      case fuchsia::net::IpAddress::Tag::kIpv6:
+        addr_in6->sin6_family = AF_INET6;
+        memmove(&addr_in6->sin6_addr, interface.addr.ipv6().addr.data(),
+                sizeof(addr_in6->sin6_addr));
+        break;
+      case fuchsia::net::IpAddress::Tag::Invalid:
+        // Should have been filtered out above.
+        UNREACHABLE();
     }
+    addresses->SetAt(addresses_idx,
+                     new InterfaceSocketAddress(
+                         reinterpret_cast<sockaddr*>(&addr),
+                         DartUtils::ScopedCopyCString(interface.name.c_str()),
+                         if_nametoindex(interface.name.c_str())));
+    addresses_idx++;
   }
-  close(fd);
   return addresses;
 }
 
diff --git a/runtime/bin/vmservice/server.dart b/runtime/bin/vmservice/server.dart
index 748ee68..8bae36d 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/runtime/bin/vmservice/server.dart
@@ -148,6 +148,7 @@
   final int _port;
   final bool _originCheckDisabled;
   final bool _authCodesDisabled;
+  final String _serviceInfoFilename;
   HttpServer _server;
   bool get running => _server != null;
 
@@ -165,7 +166,7 @@
   // On Fuchsia, authentication codes are disabled by default. To enable, the authentication token
   // would have to be written into the hub alongside the port number.
   Server(this._service, this._ip, this._port, this._originCheckDisabled,
-      bool authCodesDisabled)
+      bool authCodesDisabled, this._serviceInfoFilename)
       : _authCodesDisabled = (authCodesDisabled || Platform.isFuchsia);
 
   bool _isAllowedOrigin(String origin) {
@@ -369,6 +370,14 @@
     client.onRequest(message); // exception free, no need to try catch
   }
 
+  Future<void> _dumpServiceInfoToFile() async {
+    final serviceInfo = <String, dynamic>{
+      'uri': serverAddress.toString(),
+    };
+    final file = File(_serviceInfoFilename);
+    file.writeAsString(json.encode(serviceInfo));
+  }
+
   Future startup() async {
     if (_server != null) {
       // Already running.
@@ -426,6 +435,9 @@
       serverPrint("Creating $path");
       new File(path)..createSync(recursive: true);
     }
+    if (_serviceInfoFilename != null && _serviceInfoFilename.isNotEmpty) {
+      _dumpServiceInfoToFile();
+    }
     // Server is up and running.
     _notifyServerState(serverAddress.toString());
     onServerAddressChange('$serverAddress');
diff --git a/runtime/bin/vmservice/vmservice_io.dart b/runtime/bin/vmservice/vmservice_io.dart
index 6d7c55f..393f1f3 100644
--- a/runtime/bin/vmservice/vmservice_io.dart
+++ b/runtime/bin/vmservice/vmservice_io.dart
@@ -29,6 +29,9 @@
 // Should the HTTP server run in devmode?
 @pragma("vm:entry-point")
 bool _originCheckDisabled;
+// Location of file to output VM service connection info.
+@pragma("vm:entry-point")
+String _serviceInfoFilename;
 @pragma("vm:entry-point")
 bool _isWindows = false;
 @pragma("vm:entry-point")
@@ -48,8 +51,8 @@
   // Lazily create service.
   var service = new VMService();
   // Lazily create server.
-  server =
-      new Server(service, _ip, _port, _originCheckDisabled, _authCodesDisabled);
+  server = new Server(service, _ip, _port, _originCheckDisabled,
+      _authCodesDisabled, _serviceInfoFilename);
 }
 
 Future cleanupCallback() async {
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index 683d4b4..b5387a7 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -114,6 +114,7 @@
                       intptr_t server_port,
                       bool dev_mode_server,
                       bool auth_codes_disabled,
+                      const char* write_service_info_filename,
                       bool trace_loading,
                       bool deterministic) {
   Dart_Isolate isolate = Dart_CurrentIsolate();
@@ -176,6 +177,11 @@
                          Dart_NewBoolean(auth_codes_disabled));
   SHUTDOWN_ON_ERROR(result);
 
+  if (write_service_info_filename != nullptr) {
+    result = DartUtils::SetStringField(library, "_serviceInfoFilename",
+                                       write_service_info_filename);
+    SHUTDOWN_ON_ERROR(result);
+  }
 // Are we running on Windows?
 #if defined(HOST_OS_WINDOWS)
   Dart_Handle is_windows = Dart_True();
diff --git a/runtime/bin/vmservice_impl.h b/runtime/bin/vmservice_impl.h
index 51e9bfc..17ec55a 100644
--- a/runtime/bin/vmservice_impl.h
+++ b/runtime/bin/vmservice_impl.h
@@ -18,6 +18,7 @@
                     intptr_t server_port,
                     bool dev_mode_server,
                     bool auth_codes_disabled,
+                    const char* write_service_info_filename,
                     bool trace_loading,
                     bool deterministic);
 
diff --git a/runtime/include/dart_embedder_api.h b/runtime/include/dart_embedder_api.h
index 61b54fd..5b283ca 100644
--- a/runtime/include/dart_embedder_api.h
+++ b/runtime/include/dart_embedder_api.h
@@ -60,6 +60,10 @@
   // Default port. See enum above for special values.
   int port;
 
+  // If non-null, connection information for the VM service will be output to a
+  // file in JSON format at the location specified.
+  const char* write_service_info_filename;
+
   // TODO(vegorov) document these ones.
   bool dev_mode;
   bool deterministic;
diff --git a/runtime/lib/async_sources.gni b/runtime/lib/async_sources.gni
index d3fef9a..86abf92 100644
--- a/runtime/lib/async_sources.gni
+++ b/runtime/lib/async_sources.gni
@@ -5,10 +5,3 @@
 # This file contains all sources for the dart:async library.
 
 async_runtime_cc_files = [ "async.cc" ]
-
-async_runtime_dart_files = [
-  "async_patch.dart",
-  "deferred_load_patch.dart",
-  "schedule_microtask_patch.dart",
-  "timer_patch.dart",
-]
diff --git a/runtime/lib/collection_sources.gni b/runtime/lib/collection_sources.gni
index c3c15fc..6a81dd3 100644
--- a/runtime/lib/collection_sources.gni
+++ b/runtime/lib/collection_sources.gni
@@ -3,10 +3,3 @@
 # BSD-style license that can be found in the LICENSE file.
 
 collection_runtime_cc_files = [ "linked_hash_map.cc" ]
-
-collection_runtime_dart_files = [
-  # collection_patch.dart needs to be the first dart file because it contains
-  # imports.
-  "collection_patch.dart",
-  "compact_hash.dart",
-]
diff --git a/runtime/lib/core_sources.gni b/runtime/lib/core_sources.gni
index 825663a..7e18428 100644
--- a/runtime/lib/core_sources.gni
+++ b/runtime/lib/core_sources.gni
@@ -24,38 +24,3 @@
   "uri.cc",
   "weak_property.cc",
 ]
-
-core_runtime_dart_files = [
-  "core_patch.dart",
-
-  # The above file needs to be first as it imports required libraries.
-  "array.dart",
-  "array_patch.dart",
-  "bigint_patch.dart",
-  "bool_patch.dart",
-  "date_patch.dart",
-  "double.dart",
-  "double_patch.dart",
-  "errors_patch.dart",
-  "expando_patch.dart",
-  "function.dart",
-  "function_patch.dart",
-  "growable_array.dart",
-  "identical_patch.dart",
-  "immutable_map.dart",
-  "integers.dart",
-  "integers_patch.dart",
-  "invocation_mirror_patch.dart",
-  "lib_prefix.dart",
-  "map_patch.dart",
-  "null_patch.dart",
-  "object_patch.dart",
-  "regexp_patch.dart",
-  "stacktrace.dart",
-  "stopwatch_patch.dart",
-  "string_buffer_patch.dart",
-  "string_patch.dart",
-  "type_patch.dart",
-  "uri_patch.dart",
-  "weak_property.dart",
-]
diff --git a/runtime/lib/developer_sources.gni b/runtime/lib/developer_sources.gni
index a613da7..9d1260f 100644
--- a/runtime/lib/developer_sources.gni
+++ b/runtime/lib/developer_sources.gni
@@ -8,11 +8,3 @@
   "profiler.cc",
   "timeline.cc",
 ]
-
-developer_runtime_dart_files = [
-  # developer.dart needs to be the first dart file because it contains
-  # imports.
-  "developer.dart",
-  "profiler.dart",
-  "timeline.dart",
-]
diff --git a/runtime/lib/ffi_sources.gni b/runtime/lib/ffi_sources.gni
index 9936dd2..85c8ef4 100644
--- a/runtime/lib/ffi_sources.gni
+++ b/runtime/lib/ffi_sources.gni
@@ -7,9 +7,3 @@
   "ffi.cc",
   "ffi_dynamic_library.cc",
 ]
-
-ffi_runtime_dart_files = [
-  "ffi_patch.dart",
-  "ffi_dynamic_library_patch.dart",
-  "ffi_native_type_patch.dart",
-]
diff --git a/runtime/lib/internal_sources.gni b/runtime/lib/internal_sources.gni
index 7c173ab..b16eafe 100644
--- a/runtime/lib/internal_sources.gni
+++ b/runtime/lib/internal_sources.gni
@@ -4,12 +4,3 @@
 
 # Sources that patch the library "dart:_internal".
 internal_runtime_cc_files = [ "class_id.cc" ]
-
-internal_runtime_dart_files = [
-  "internal_patch.dart",
-
-  # The above file needs to be first as it imports required libraries.
-  "class_id.dart",
-  "print_patch.dart",
-  "symbol_patch.dart",
-]
diff --git a/runtime/lib/isolate_sources.gni b/runtime/lib/isolate_sources.gni
index 1495aaf..be6661d 100644
--- a/runtime/lib/isolate_sources.gni
+++ b/runtime/lib/isolate_sources.gni
@@ -4,8 +4,3 @@
 
 # This file contains all sources for the dart:isolate library.
 isolate_runtime_cc_files = [ "isolate.cc" ]
-
-isolate_runtime_dart_files = [
-  "isolate_patch.dart",
-  "timer_impl.dart",
-]
diff --git a/runtime/lib/math_sources.gni b/runtime/lib/math_sources.gni
index 986010d..1155ac4 100644
--- a/runtime/lib/math_sources.gni
+++ b/runtime/lib/math_sources.gni
@@ -3,5 +3,3 @@
 # BSD-style license that can be found in the LICENSE file.
 
 math_runtime_cc_files = [ "math.cc" ]
-
-math_runtime_dart_files = [ "math_patch.dart" ]
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index a76d721..846e8ab 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -177,7 +177,7 @@
     args.SetAt(6, is_final);
     args.SetAt(7, default_value);
     args.SetAt(8, metadata);
-    param = CreateMirror(Symbols::_LocalParameterMirror(), args);
+    param = CreateMirror(Symbols::_ParameterMirror(), args);
     results.SetAt(i, param);
   }
   results.MakeImmutable();
@@ -190,7 +190,7 @@
   args.SetAt(0, param);
   args.SetAt(1, String::Handle(param.name()));
   args.SetAt(2, owner_mirror);
-  return CreateMirror(Symbols::_LocalTypeVariableMirror(), args);
+  return CreateMirror(Symbols::_TypeVariableMirror(), args);
 }
 
 // We create a list in native code and let Dart code create the type mirror
@@ -225,7 +225,7 @@
   args.SetAt(3, Bool::Get(cls.IsGeneric()));
   args.SetAt(4, cls.IsGeneric() ? is_declaration : Bool::False());
   args.SetAt(5, owner_mirror);
-  return CreateMirror(Symbols::_LocalTypedefMirror(), args);
+  return CreateMirror(Symbols::_TypedefMirror(), args);
 }
 
 static RawInstance* CreateFunctionTypeMirror(const AbstractType& type) {
@@ -236,7 +236,7 @@
   args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
   args.SetAt(1, MirrorReference::Handle(MirrorReference::New(func)));
   args.SetAt(2, type);
-  return CreateMirror(Symbols::_LocalFunctionTypeMirror(), args);
+  return CreateMirror(Symbols::_FunctionTypeMirror(), args);
 }
 
 static RawInstance* CreateMethodMirror(const Function& func,
@@ -276,7 +276,7 @@
   kind_flags |= (static_cast<intptr_t>(is_synthetic) << Mirrors::kSynthetic);
   args.SetAt(5, Smi::Handle(Smi::New(kind_flags)));
 
-  return CreateMirror(Symbols::_LocalMethodMirror(), args);
+  return CreateMirror(Symbols::_MethodMirror(), args);
 }
 
 static RawInstance* CreateVariableMirror(const Field& field,
@@ -295,7 +295,7 @@
   args.SetAt(5, Bool::Get(field.is_final()));
   args.SetAt(6, Bool::Get(field.is_const()));
 
-  return CreateMirror(Symbols::_LocalVariableMirror(), args);
+  return CreateMirror(Symbols::_VariableMirror(), args);
 }
 
 static RawInstance* CreateClassMirror(const Class& cls,
@@ -326,7 +326,7 @@
   args.SetAt(6, Bool::Get(cls.is_transformed_mixin_application()));
   args.SetAt(7, cls.NumTypeParameters() == 0 ? Bool::False() : is_declaration);
   args.SetAt(8, Bool::Get(cls.is_enum_class()));
-  return CreateMirror(Symbols::_LocalClassMirror(), args);
+  return CreateMirror(Symbols::_ClassMirror(), args);
 }
 
 static bool IsCensoredLibrary(const String& url) {
@@ -360,7 +360,7 @@
     return Instance::null();
   }
   args.SetAt(2, str);
-  return CreateMirror(Symbols::_LocalLibraryMirror(), args);
+  return CreateMirror(Symbols::_LibraryMirror(), args);
 }
 
 static RawInstance* CreateCombinatorMirror(const Object& identifiers,
@@ -368,7 +368,7 @@
   const Array& args = Array::Handle(Array::New(2));
   args.SetAt(0, identifiers);
   args.SetAt(1, Bool::Get(is_show));
-  return CreateMirror(Symbols::_LocalCombinatorMirror(), args);
+  return CreateMirror(Symbols::_CombinatorMirror(), args);
 }
 
 static RawInstance* CreateLibraryDependencyMirror(Thread* thread,
@@ -419,7 +419,7 @@
   args.SetAt(4, Bool::Get(is_import));
   args.SetAt(5, Bool::Get(is_deferred));
   args.SetAt(6, metadata);
-  return CreateMirror(Symbols::_LocalLibraryDependencyMirror(), args);
+  return CreateMirror(Symbols::_LibraryDependencyMirror(), args);
 }
 
 static RawInstance* CreateLibraryDependencyMirror(Thread* thread,
@@ -644,7 +644,7 @@
   const Array& args = Array::Handle(Array::New(2));
   args.SetAt(0, debug_name);
   args.SetAt(1, root_library_mirror);
-  return CreateMirror(Symbols::_LocalIsolateMirror(), args);
+  return CreateMirror(Symbols::_IsolateMirror(), args);
 }
 
 static void VerifyMethodKindShifts() {
@@ -653,7 +653,7 @@
   Zone* zone = thread->zone();
   const Library& lib = Library::Handle(zone, Library::MirrorsLibrary());
   const Class& cls = Class::Handle(
-      zone, lib.LookupClassAllowPrivate(Symbols::_LocalMethodMirror()));
+      zone, lib.LookupClassAllowPrivate(Symbols::_MethodMirror()));
   Error& error = Error::Handle(zone);
   error ^= cls.EnsureIsFinalized(thread);
   ASSERT(error.IsNull());
diff --git a/runtime/lib/mirrors_sources.gni b/runtime/lib/mirrors_sources.gni
index e92dcf0..3b237a2 100644
--- a/runtime/lib/mirrors_sources.gni
+++ b/runtime/lib/mirrors_sources.gni
@@ -7,11 +7,3 @@
   "mirrors.cc",
   "mirrors.h",
 ]
-
-mirrors_runtime_dart_files = [
-  # mirrors_patch.dart needs to be the first dart file because it contains
-  # imports.
-  "mirrors_patch.dart",
-  "mirrors_impl.dart",
-  "mirror_reference.dart",
-]
diff --git a/runtime/lib/typed_data_sources.gni b/runtime/lib/typed_data_sources.gni
index b10a829..feebd40 100644
--- a/runtime/lib/typed_data_sources.gni
+++ b/runtime/lib/typed_data_sources.gni
@@ -7,5 +7,3 @@
   "typed_data.cc",
   "simd128.cc",
 ]
-
-typed_data_runtime_dart_files = [ "typed_data_patch.dart" ]
diff --git a/runtime/lib/wasm.cc b/runtime/lib/wasm.cc
index 7d0c06f..d4f315d 100644
--- a/runtime/lib/wasm.cc
+++ b/runtime/lib/wasm.cc
@@ -2,27 +2,661 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+#ifdef DART_ENABLE_WASM
+
+#include <memory>
+#include <sstream>
+
 #include "platform/unicode.h"
+#include "third_party/wasmer/wasmer.hh"
 #include "vm/bootstrap_natives.h"
+#include "vm/dart_api_state.h"
 #include "vm/dart_entry.h"
+#include "vm/exceptions.h"
 
 namespace dart {
 
-int callWasm(const char* name, int n) {
-  return 100 * n;
+static void ThrowWasmerError() {
+  TransitionNativeToVM transition(Thread::Current());
+  String& error = String::Handle();
+  {
+    int len = wasmer_last_error_length();
+    auto raw_error = std::unique_ptr<char[]>(new char[len]);
+    int read_len = wasmer_last_error_message(raw_error.get(), len);
+    ASSERT(read_len == len);
+    error = String::NewFormatted("Wasmer error: %s", raw_error.get());
+  }
+  Exceptions::ThrowArgumentError(error);
 }
 
-// This is a temporary API for prototyping.
+template <typename T>
+static void Finalize(void* isolate_callback_data,
+                     Dart_WeakPersistentHandle handle,
+                     void* peer) {
+  delete reinterpret_cast<T*>(peer);
+}
+
+static void FinalizeWasmModule(void* isolate_callback_data,
+                               Dart_WeakPersistentHandle handle,
+                               void* module) {
+  wasmer_module_destroy(reinterpret_cast<wasmer_module_t*>(module));
+}
+
+static void FinalizeWasmMemory(void* isolate_callback_data,
+                               Dart_WeakPersistentHandle handle,
+                               void* memory) {
+  wasmer_memory_destroy(reinterpret_cast<wasmer_memory_t*>(memory));
+}
+
+static std::unique_ptr<char[]> ToUTF8(const String& str) {
+  const intptr_t str_size = Utf8::Length(str);
+  auto str_raw = std::unique_ptr<char[]>(new char[str_size + 1]);
+  str.ToUTF8(reinterpret_cast<uint8_t*>(str_raw.get()), str_size);
+  str_raw[str_size] = '\0';
+  return str_raw;
+}
+
+static bool ToWasmValue(const Number& value,
+                        classid_t type,
+                        wasmer_value_t* out) {
+  switch (type) {
+    case kWasmInt32Cid:
+      if (!value.IsInteger()) return false;
+      out->tag = wasmer_value_tag::WASM_I32;
+      out->value.I32 = Integer::Cast(value).AsInt64Value();
+      return true;
+    case kWasmInt64Cid:
+      if (!value.IsInteger()) return false;
+      out->tag = wasmer_value_tag::WASM_I64;
+      out->value.I64 = Integer::Cast(value).AsInt64Value();
+      return true;
+    case kWasmFloatCid:
+      if (!value.IsDouble()) return false;
+      out->tag = wasmer_value_tag::WASM_F32;
+      out->value.F32 = Double::Cast(value).value();
+      return true;
+    case kWasmDoubleCid:
+      if (!value.IsDouble()) return false;
+      out->tag = wasmer_value_tag::WASM_F64;
+      out->value.F64 = Double::Cast(value).value();
+      return true;
+    default:
+      return false;
+  }
+}
+
+static RawObject* ToDartObject(wasmer_value_t ret) {
+  switch (ret.tag) {
+    case wasmer_value_tag::WASM_I32:
+      return Integer::New(ret.value.I32);
+    case wasmer_value_tag::WASM_I64:
+      return Integer::New(ret.value.I64);
+    case wasmer_value_tag::WASM_F32:
+      return Double::New(ret.value.F32);
+    case wasmer_value_tag::WASM_F64:
+      return Double::New(ret.value.F64);
+    default:
+      FATAL("Unknown WASM type");
+      return nullptr;
+  }
+}
+
+RawExternalTypedData* WasmMemoryToExternalTypedData(wasmer_memory_t* memory) {
+  uint8_t* data = wasmer_memory_data(memory);
+  uint32_t size = wasmer_memory_data_length(memory);
+  return ExternalTypedData::New(kExternalTypedDataUint8ArrayCid, data, size);
+}
+
+class WasmImports {
+ public:
+  explicit WasmImports(std::unique_ptr<char[]> module_name)
+      : _module_name(std::move(module_name)) {}
+
+  ~WasmImports() {
+    for (wasmer_global_t* global : _globals) {
+      wasmer_global_destroy(global);
+    }
+    for (const char* name : _import_names) {
+      delete[] name;
+    }
+  }
+
+  size_t NumImports() const { return _imports.length(); }
+  wasmer_import_t* RawImports() { return _imports.data(); }
+
+  void AddMemory(std::unique_ptr<char[]> name, wasmer_memory_t* memory) {
+    AddImport(std::move(name), wasmer_import_export_kind::WASM_MEMORY)->memory =
+        memory;
+  }
+
+  void AddGlobal(std::unique_ptr<char[]> name,
+                 wasmer_value_t value,
+                 bool mutable_) {
+    wasmer_global_t* global = wasmer_global_new(value, mutable_);
+    _globals.Add(global);
+    AddImport(std::move(name), wasmer_import_export_kind::WASM_GLOBAL)->global =
+        global;
+  }
+
+ private:
+  std::unique_ptr<char[]> _module_name;
+  MallocGrowableArray<const char*> _import_names;
+  MallocGrowableArray<wasmer_global_t*> _globals;
+  MallocGrowableArray<wasmer_import_t> _imports;
+
+  wasmer_import_export_value* AddImport(std::unique_ptr<char[]> name,
+                                        wasmer_import_export_kind tag) {
+    wasmer_import_t import;
+    import.module_name.bytes =
+        reinterpret_cast<const uint8_t*>(_module_name.get());
+    import.module_name.bytes_len = (uint32_t)strlen(_module_name.get());
+    import.import_name.bytes = reinterpret_cast<const uint8_t*>(name.get());
+    import.import_name.bytes_len = (uint32_t)strlen(name.get());
+    import.tag = tag;
+    _import_names.Add(name.release());
+    _imports.Add(import);
+    return &_imports.Last().value;
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(WasmImports);
+};
+
+class WasmFunction {
+ public:
+  WasmFunction(MallocGrowableArray<classid_t> args,
+               classid_t ret,
+               const wasmer_export_func_t* fn)
+      : _args(std::move(args)), _ret(ret), _fn(fn) {}
+  bool IsVoid() const { return _ret == kWasmVoidCid; }
+  const MallocGrowableArray<classid_t>& args() const { return _args; }
+
+  bool SignatureMatches(const MallocGrowableArray<classid_t>& dart_args,
+                        classid_t dart_ret) {
+    if (dart_args.length() != _args.length()) {
+      return false;
+    }
+    for (intptr_t i = 0; i < dart_args.length(); ++i) {
+      if (dart_args[i] != _args[i]) {
+        return false;
+      }
+    }
+    return dart_ret == _ret;
+  }
+
+  bool Call(const wasmer_value_t* params, wasmer_value_t* result) {
+    return wasmer_export_func_call(_fn, params, _args.length(), result,
+                                   IsVoid() ? 0 : 1) ==
+           wasmer_result_t::WASMER_OK;
+  }
+
+  void Print(std::ostream& o, const char* name) const {
+    PrintDartType(o, _ret);
+    o << ' ' << name << '(';
+    for (intptr_t i = 0; i < _args.length(); ++i) {
+      if (i > 0) o << ", ";
+      PrintDartType(o, _args[i]);
+    }
+    o << ')';
+  }
+
+ private:
+  MallocGrowableArray<classid_t> _args;
+  const classid_t _ret;
+  const wasmer_export_func_t* _fn;
+
+  static void PrintDartType(std::ostream& o, classid_t type) {
+    switch (type) {
+      case kWasmInt32Cid:
+        o << "i32";
+        break;
+      case kWasmInt64Cid:
+        o << "i64";
+        break;
+      case kWasmFloatCid:
+        o << "f32";
+        break;
+      case kWasmDoubleCid:
+        o << "f64";
+        break;
+      case kWasmVoidCid:
+        o << "void";
+        break;
+    }
+  }
+};
+
+class WasmInstance {
+ public:
+  WasmInstance() : _instance(nullptr), _exports(nullptr) {}
+
+  bool Instantiate(wasmer_module_t* module, WasmImports* imports) {
+    // Instantiate module.
+    if (wasmer_module_instantiate(module, &_instance, imports->RawImports(),
+                                  imports->NumImports()) !=
+        wasmer_result_t::WASMER_OK) {
+      return false;
+    }
+
+    // Load all functions.
+    wasmer_instance_exports(_instance, &_exports);
+    intptr_t num_exports = wasmer_exports_len(_exports);
+    for (intptr_t i = 0; i < num_exports; ++i) {
+      wasmer_export_t* exp = wasmer_exports_get(_exports, i);
+      if (wasmer_export_kind(exp) == wasmer_import_export_kind::WASM_FUNCTION) {
+        if (!AddFunction(exp)) {
+          return false;
+        }
+      }
+    }
+
+    return true;
+  }
+
+  ~WasmInstance() {
+    auto it = _functions.GetIterator();
+    for (auto* kv = it.Next(); kv; kv = it.Next()) {
+      delete[] kv->key;
+      delete kv->value;
+    }
+    if (_exports != nullptr) {
+      wasmer_exports_destroy(_exports);
+    }
+    if (_instance != nullptr) {
+      wasmer_instance_destroy(_instance);
+    }
+  }
+
+  WasmFunction* GetFunction(const char* name,
+                            const MallocGrowableArray<classid_t>& dart_args,
+                            classid_t dart_ret,
+                            String* error) {
+    WasmFunction* fn = _functions.LookupValue(name);
+    if (fn == nullptr) {
+      *error = String::NewFormatted(
+          "Couldn't find a function called %s in the WASM module's exports",
+          name);
+      return nullptr;
+    }
+    if (!fn->SignatureMatches(dart_args, dart_ret)) {
+      std::stringstream sig;
+      fn->Print(sig, name);
+      *error = String::NewFormatted("Function signature doesn't match: %s",
+                                    sig.str().c_str());
+      return nullptr;
+    }
+    return fn;
+  }
+
+  void PrintFunctions(std::ostream& o) const {
+    o << '{' << std::endl;
+    auto it = _functions.GetIterator();
+    for (auto* kv = it.Next(); kv; kv = it.Next()) {
+      kv->value->Print(o, kv->key);
+      o << std::endl;
+    }
+    o << '}' << std::endl;
+  }
+
+ private:
+  wasmer_instance_t* _instance;
+  wasmer_exports_t* _exports;
+  MallocDirectChainedHashMap<CStringKeyValueTrait<WasmFunction*>> _functions;
+
+  static classid_t ToDartType(wasmer_value_tag wasm_type) {
+    switch (wasm_type) {
+      case wasmer_value_tag::WASM_I32:
+        return kWasmInt32Cid;
+      case wasmer_value_tag::WASM_I64:
+        return kWasmInt64Cid;
+      case wasmer_value_tag::WASM_F32:
+        return kWasmFloatCid;
+      case wasmer_value_tag::WASM_F64:
+        return kWasmDoubleCid;
+    }
+    FATAL("Unknown WASM type");
+    return 0;
+  }
+
+  bool AddFunction(wasmer_export_t* exp) {
+    const wasmer_export_func_t* fn = wasmer_export_to_func(exp);
+
+    uint32_t num_rets;
+    if (wasmer_export_func_returns_arity(fn, &num_rets) !=
+        wasmer_result_t::WASMER_OK) {
+      return false;
+    }
+    ASSERT(num_rets <= 1);
+    wasmer_value_tag wasm_ret;
+    if (wasmer_export_func_returns(fn, &wasm_ret, num_rets) !=
+        wasmer_result_t::WASMER_OK) {
+      return false;
+    }
+    classid_t ret = num_rets == 0 ? kWasmVoidCid : ToDartType(wasm_ret);
+
+    uint32_t num_args;
+    if (wasmer_export_func_params_arity(fn, &num_args) !=
+        wasmer_result_t::WASMER_OK) {
+      return false;
+    }
+    auto wasm_args =
+        std::unique_ptr<wasmer_value_tag[]>(new wasmer_value_tag[num_args]);
+    if (wasmer_export_func_params(fn, wasm_args.get(), num_args) !=
+        wasmer_result_t::WASMER_OK) {
+      return false;
+    }
+    MallocGrowableArray<classid_t> args;
+    for (intptr_t i = 0; i < num_args; ++i) {
+      args.Add(ToDartType(wasm_args[i]));
+    }
+
+    wasmer_byte_array name_bytes = wasmer_export_name(exp);
+    char* name = new char[name_bytes.bytes_len + 1];
+    for (size_t i = 0; i < name_bytes.bytes_len; ++i) {
+      name[i] = name_bytes.bytes[i];
+    }
+    name[name_bytes.bytes_len] = '\0';
+
+    _functions.Insert({name, new WasmFunction(std::move(args), ret, fn)});
+    return true;
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(WasmInstance);
+};
+
+DEFINE_NATIVE_ENTRY(Wasm_initModule, 0, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, mod_wrap, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(TypedDataBase, data, arguments->NativeArgAt(1));
+
+  ASSERT(mod_wrap.NumNativeFields() == 1);
+
+  std::unique_ptr<uint8_t[]> data_copy;
+  intptr_t len;
+  {
+    NoSafepointScope scope(thread);
+    len = data.LengthInBytes();
+    data_copy = std::unique_ptr<uint8_t[]>(new uint8_t[len]);
+    // The memory does not overlap.
+    memcpy(data_copy.get(), data.DataAddr(0), len);  // NOLINT
+  }
+
+  wasmer_module_t* module;
+  {
+    TransitionVMToNative transition(thread);
+    if (wasmer_compile(&module, data_copy.get(), len) !=
+        wasmer_result_t::WASMER_OK) {
+      data_copy.reset();
+      ThrowWasmerError();
+    }
+  }
+
+  mod_wrap.SetNativeField(0, reinterpret_cast<intptr_t>(module));
+  FinalizablePersistentHandle::New(thread->isolate(), mod_wrap, module,
+                                   FinalizeWasmModule, len);
+
+  return Object::null();
+}
+
+DEFINE_NATIVE_ENTRY(Wasm_initImports, 0, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, imp_wrap, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(String, module_name, arguments->NativeArgAt(1));
+
+  ASSERT(imp_wrap.NumNativeFields() == 1);
+
+  WasmImports* imports = new WasmImports(ToUTF8(module_name));
+
+  imp_wrap.SetNativeField(0, reinterpret_cast<intptr_t>(imports));
+  FinalizablePersistentHandle::New(thread->isolate(), imp_wrap, imports,
+                                   Finalize<WasmImports>, sizeof(WasmImports));
+
+  return Object::null();
+}
+
+DEFINE_NATIVE_ENTRY(Wasm_addMemoryImport, 0, 3) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, imp_wrap, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, mem_wrap, arguments->NativeArgAt(2));
+
+  ASSERT(imp_wrap.NumNativeFields() == 1);
+  ASSERT(mem_wrap.NumNativeFields() == 1);
+
+  WasmImports* imports =
+      reinterpret_cast<WasmImports*>(imp_wrap.GetNativeField(0));
+  wasmer_memory_t* memory =
+      reinterpret_cast<wasmer_memory_t*>(mem_wrap.GetNativeField(0));
+
+  imports->AddMemory(ToUTF8(name), memory);
+
+  return Object::null();
+}
+
+DEFINE_NATIVE_ENTRY(Wasm_addGlobalImport, 0, 5) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, imp_wrap, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Number, value, arguments->NativeArgAt(2));
+  GET_NON_NULL_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(3));
+  GET_NON_NULL_NATIVE_ARGUMENT(Bool, mutable_, arguments->NativeArgAt(4));
+
+  ASSERT(imp_wrap.NumNativeFields() == 1);
+
+  WasmImports* imports =
+      reinterpret_cast<WasmImports*>(imp_wrap.GetNativeField(0));
+  wasmer_value_t wasm_value;
+  if (!ToWasmValue(value, type.type_class_id(), &wasm_value)) {
+    Exceptions::ThrowArgumentError(String::Handle(String::NewFormatted(
+        "Can't convert dart value to WASM global variable")));
+  }
+
+  imports->AddGlobal(ToUTF8(name), wasm_value, mutable_.value());
+
+  return Object::null();
+}
+
+DEFINE_NATIVE_ENTRY(Wasm_initMemory, 0, 3) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, mem_wrap, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, init, arguments->NativeArgAt(1));
+  GET_NATIVE_ARGUMENT(Integer, max, arguments->NativeArgAt(2));
+
+  ASSERT(mem_wrap.NumNativeFields() == 1);
+  const int64_t init_size = init.AsInt64Value();
+  const int64_t max_size = max.AsInt64Value();
+
+  wasmer_memory_t* memory;
+  wasmer_limits_t descriptor;
+  descriptor.min = init_size;
+  if (max_size < 0) {
+    descriptor.max.has_some = false;
+  } else {
+    descriptor.max.has_some = true;
+    descriptor.max.some = max_size;
+  }
+  if (wasmer_memory_new(&memory, descriptor) != wasmer_result_t::WASMER_OK) {
+    ThrowWasmerError();
+  }
+  mem_wrap.SetNativeField(0, reinterpret_cast<intptr_t>(memory));
+  FinalizablePersistentHandle::New(thread->isolate(), mem_wrap, memory,
+                                   FinalizeWasmMemory, init_size);
+  return WasmMemoryToExternalTypedData(memory);
+}
+
+DEFINE_NATIVE_ENTRY(Wasm_growMemory, 0, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, mem_wrap, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, delta, arguments->NativeArgAt(1));
+
+  ASSERT(mem_wrap.NumNativeFields() == 1);
+
+  wasmer_memory_t* memory =
+      reinterpret_cast<wasmer_memory_t*>(mem_wrap.GetNativeField(0));
+  if (wasmer_memory_grow(memory, delta.AsInt64Value()) !=
+      wasmer_result_t::WASMER_OK) {
+    ThrowWasmerError();
+  }
+  return WasmMemoryToExternalTypedData(memory);
+}
+
+DEFINE_NATIVE_ENTRY(Wasm_initInstance, 0, 3) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, inst_wrap, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, mod_wrap, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, imp_wrap, arguments->NativeArgAt(2));
+
+  ASSERT(inst_wrap.NumNativeFields() == 1);
+  ASSERT(mod_wrap.NumNativeFields() == 1);
+  ASSERT(imp_wrap.NumNativeFields() == 1);
+
+  wasmer_module_t* module =
+      reinterpret_cast<wasmer_module_t*>(mod_wrap.GetNativeField(0));
+  WasmImports* imports =
+      reinterpret_cast<WasmImports*>(imp_wrap.GetNativeField(0));
+
+  WasmInstance* inst = nullptr;
+  {
+    TransitionVMToNative transition(thread);
+    inst = new WasmInstance();
+    if (!inst->Instantiate(module, imports)) {
+      delete inst;
+      inst = nullptr;
+    }
+  }
+  if (inst == nullptr) {
+    ThrowWasmerError();
+  }
+
+  inst_wrap.SetNativeField(0, reinterpret_cast<intptr_t>(inst));
+  FinalizablePersistentHandle::New(thread->isolate(), inst_wrap, inst,
+                                   Finalize<WasmInstance>,
+                                   sizeof(WasmInstance));
+
+  return Object::null();
+}
+
+DEFINE_NATIVE_ENTRY(Wasm_initFunction, 0, 4) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, fn_wrap, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, inst_wrap, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(2));
+  GET_NON_NULL_NATIVE_ARGUMENT(Type, fn_type, arguments->NativeArgAt(3));
+
+  ASSERT(fn_wrap.NumNativeFields() == 1);
+  ASSERT(inst_wrap.NumNativeFields() == 1);
+
+  WasmInstance* inst =
+      reinterpret_cast<WasmInstance*>(inst_wrap.GetNativeField(0));
+
+  WasmFunction* fn;
+  String& error = String::Handle(zone);
+
+  {
+    Function& sig = Function::Handle(fn_type.signature());
+    Array& args = Array::Handle(sig.parameter_types());
+    MallocGrowableArray<classid_t> dart_args;
+    for (intptr_t i = sig.NumImplicitParameters(); i < args.Length(); ++i) {
+      dart_args.Add(
+          AbstractType::Cast(Object::Handle(args.At(i))).type_class_id());
+    }
+    classid_t dart_ret =
+        AbstractType::Handle(sig.result_type()).type_class_id();
+
+    std::unique_ptr<char[]> name_raw = ToUTF8(name);
+    fn = inst->GetFunction(name_raw.get(), dart_args, dart_ret, &error);
+  }
+
+  if (fn == nullptr) {
+    Exceptions::ThrowArgumentError(error);
+  }
+
+  fn_wrap.SetNativeField(0, reinterpret_cast<intptr_t>(fn));
+  // Don't need a finalizer because WasmFunctions are owned their WasmInstance.
+
+  return Object::null();
+}
+
 DEFINE_NATIVE_ENTRY(Wasm_callFunction, 0, 2) {
-  GET_NON_NULL_NATIVE_ARGUMENT(String, fn_name, arguments->NativeArgAt(0));
-  GET_NON_NULL_NATIVE_ARGUMENT(Integer, arg, arguments->NativeArgAt(1));
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, fn_wrap, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(1));
 
-  intptr_t len = Utf8::Length(fn_name);
-  std::unique_ptr<char> name = std::unique_ptr<char>(new char[len + 1]);
-  fn_name.ToUTF8(reinterpret_cast<uint8_t*>(name.get()), len);
-  name.get()[len] = 0;
+  ASSERT(fn_wrap.NumNativeFields() == 1);
+  WasmFunction* fn = reinterpret_cast<WasmFunction*>(fn_wrap.GetNativeField(0));
 
-  return Smi::New(callWasm(name.get(), arg.AsInt64Value()));
+  if (args.Length() != fn->args().length()) {
+    Exceptions::ThrowArgumentError(String::Handle(String::NewFormatted(
+        "Wrong number of args. Expected %" Pu " but found %" Pd ".",
+        fn->args().length(), args.Length())));
+  }
+  auto params = std::unique_ptr<wasmer_value_t[]>(
+      new wasmer_value_t[fn->args().length()]);
+  for (intptr_t i = 0; i < args.Length(); ++i) {
+    if (!ToWasmValue(Number::Cast(Object::Handle(args.At(i))), fn->args()[i],
+                     &params[i])) {
+      params.reset();
+      Exceptions::ThrowArgumentError(String::Handle(
+          String::NewFormatted("Arg %" Pd " is the wrong type.", i)));
+    }
+  }
+
+  wasmer_value_t ret;
+  {
+    TransitionVMToNative transition(thread);
+    if (!fn->Call(params.get(), &ret)) {
+      params.reset();
+      ThrowWasmerError();
+    }
+  }
+  return fn->IsVoid() ? Object::null() : ToDartObject(ret);
 }
 
 }  // namespace dart
+
+#else  // DART_ENABLE_WASM
+
+#include "vm/bootstrap_natives.h"
+#include "vm/dart_entry.h"
+#include "vm/exceptions.h"
+
+namespace dart {
+
+DEFINE_NATIVE_ENTRY(Wasm_initModule, 0, 2) {
+  Exceptions::ThrowUnsupportedError("WASM is disabled");
+  return nullptr;
+}
+
+DEFINE_NATIVE_ENTRY(Wasm_initImports, 0, 2) {
+  Exceptions::ThrowUnsupportedError("WASM is disabled");
+  return nullptr;
+}
+
+DEFINE_NATIVE_ENTRY(Wasm_addMemoryImport, 0, 3) {
+  Exceptions::ThrowUnsupportedError("WASM is disabled");
+  return nullptr;
+}
+
+DEFINE_NATIVE_ENTRY(Wasm_addGlobalImport, 0, 5) {
+  Exceptions::ThrowUnsupportedError("WASM is disabled");
+  return nullptr;
+}
+
+DEFINE_NATIVE_ENTRY(Wasm_initMemory, 0, 3) {
+  Exceptions::ThrowUnsupportedError("WASM is disabled");
+  return nullptr;
+}
+
+DEFINE_NATIVE_ENTRY(Wasm_growMemory, 0, 3) {
+  Exceptions::ThrowUnsupportedError("WASM is disabled");
+  return nullptr;
+}
+
+DEFINE_NATIVE_ENTRY(Wasm_initInstance, 0, 3) {
+  Exceptions::ThrowUnsupportedError("WASM is disabled");
+  return nullptr;
+}
+
+DEFINE_NATIVE_ENTRY(Wasm_initFunction, 0, 4) {
+  Exceptions::ThrowUnsupportedError("WASM is disabled");
+  return nullptr;
+}
+
+DEFINE_NATIVE_ENTRY(Wasm_callFunction, 0, 2) {
+  Exceptions::ThrowUnsupportedError("WASM is disabled");
+  return nullptr;
+}
+
+}  // namespace dart
+
+#endif  // DART_ENABLE_WASM
diff --git a/runtime/lib/wasm_sources.gni b/runtime/lib/wasm_sources.gni
index 6067612..2e7faff 100644
--- a/runtime/lib/wasm_sources.gni
+++ b/runtime/lib/wasm_sources.gni
@@ -3,5 +3,3 @@
 # BSD-style license that can be found in the LICENSE file.
 
 wasm_runtime_cc_files = [ "wasm.cc" ]
-
-wasm_runtime_dart_files = [ "wasm_patch.dart" ]
diff --git a/runtime/observatory/lib/src/elements/native_memory_profiler.dart b/runtime/observatory/lib/src/elements/native_memory_profiler.dart
index 4d874b5..dfbe459 100644
--- a/runtime/observatory/lib/src/elements/native_memory_profiler.dart
+++ b/runtime/observatory/lib/src/elements/native_memory_profiler.dart
@@ -145,6 +145,11 @@
   }
 
   Future _request({bool forceFetch: false}) async {
+    if (forceFetch) {
+      for (M.Isolate isolate in _vm.isolates) {
+        await isolate.collectAllGarbage();
+      }
+    }
     _progress = null;
     _progressStream = _profiles.get(_vm, _tag, forceFetch: forceFetch);
     _r.dirty();
diff --git a/runtime/observatory/lib/src/models/objects/isolate.dart b/runtime/observatory/lib/src/models/objects/isolate.dart
index f1d1147..039e0bd 100644
--- a/runtime/observatory/lib/src/models/objects/isolate.dart
+++ b/runtime/observatory/lib/src/models/objects/isolate.dart
@@ -14,6 +14,9 @@
 
   /// A name identifying this isolate. Not guaranteed to be unique.
   String get name;
+
+  /// Trigger a full GC, collecting all unreachable or weakly reachable objects.
+  Future collectAllGarbage();
 }
 
 enum IsolateStatus { loading, idle, running, paused }
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index afbb7cc..fffb41c 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -1330,6 +1330,10 @@
     }
   }
 
+  Future collectAllGarbage() {
+    return invokeRpc('_collectAllGarbage', {});
+  }
+
   /// Fetches and builds the class hierarchy for this isolate. Returns the
   /// Object class object.
   Future<Class> getClassHierarchy() async {
diff --git a/runtime/observatory/tests/service/add_breakpoint_rpc_test.dart b/runtime/observatory/tests/service/add_breakpoint_rpc_test.dart
deleted file mode 100644
index 4c2c388..0000000
--- a/runtime/observatory/tests/service/add_breakpoint_rpc_test.dart
+++ /dev/null
@@ -1,139 +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:observatory/service_io.dart';
-import 'package:unittest/unittest.dart';
-import 'service_test_common.dart';
-import 'test_helper.dart';
-import 'dart:async';
-
-const int LINE_A = 22;
-const int LINE_B = 24;
-
-int value = 0;
-
-int incValue(int amount) {
-  value += amount;
-  return amount;
-}
-
-Future testMain() async {
-  incValue(incValue(1)); // line A.
-
-  incValue(incValue(1)); // line B.
-}
-
-var tests = <IsolateTest>[
-  hasPausedAtStart,
-
-  // Test future breakpoints.
-  (Isolate isolate) async {
-    var rootLib = isolate.rootLibrary;
-    await rootLib.load();
-    var script = rootLib.scripts[0];
-
-    // Future breakpoint.
-    var futureBpt1 = await isolate.addBreakpoint(script, LINE_A);
-    expect(futureBpt1.number, equals(1));
-    expect(futureBpt1.resolved, isFalse);
-    expect(await futureBpt1.location.getLine(), equals(LINE_A));
-    expect(await futureBpt1.location.getColumn(), equals(null));
-
-    // Future breakpoint with specific column.
-    var futureBpt2 = await isolate.addBreakpoint(script, LINE_A, 3);
-    expect(futureBpt2.number, equals(2));
-    expect(futureBpt2.resolved, isFalse);
-    expect(await futureBpt2.location.getLine(), equals(LINE_A));
-    expect(await futureBpt2.location.getColumn(), equals(3));
-
-    var stream = await isolate.vm.getEventStream(VM.kDebugStream);
-    Completer completer = new Completer();
-    var subscription;
-    var resolvedCount = 0;
-    subscription = stream.listen((ServiceEvent event) async {
-      if (event.kind == ServiceEvent.kBreakpointResolved) {
-        resolvedCount++;
-      }
-      if (event.kind == ServiceEvent.kPauseBreakpoint) {
-        subscription.cancel();
-        completer.complete();
-      }
-    });
-    await isolate.resume();
-    await completer.future;
-
-    // After resolution the breakpoints have assigned line & column.
-    expect(resolvedCount, equals(2));
-    expect(futureBpt1.resolved, isTrue);
-    expect(await futureBpt1.location.getLine(), equals(LINE_A));
-    expect(await futureBpt1.location.getColumn(), equals(12));
-    expect(futureBpt2.resolved, isTrue);
-    expect(await futureBpt2.location.getLine(), equals(LINE_A));
-    expect(await futureBpt2.location.getColumn(), equals(3));
-
-    // The first breakpoint hits before value is modified.
-    expect(((await rootLib.evaluate('value')) as Instance).valueAsString,
-        equals('0'));
-
-    stream = await isolate.vm.getEventStream(VM.kDebugStream);
-    completer = new Completer();
-    subscription = stream.listen((ServiceEvent event) async {
-      if (event.kind == ServiceEvent.kPauseBreakpoint) {
-        subscription.cancel();
-        completer.complete();
-      }
-    });
-    await isolate.resume();
-    await completer.future;
-
-    // The second breakpoint hits after value has been modified once.
-    expect(((await rootLib.evaluate('value')) as Instance).valueAsString,
-        equals('1'));
-
-    // Remove the breakpoints.
-    expect(
-        (await isolate.removeBreakpoint(futureBpt1)).type, equals('Success'));
-    expect(
-        (await isolate.removeBreakpoint(futureBpt2)).type, equals('Success'));
-  },
-
-  // Test resolution of column breakpoints.
-  (Isolate isolate) async {
-    var script = isolate.rootLibrary.scripts[0];
-    // Try all columns, including some columns that are too big.
-    for (int col = 1; col <= 50; col++) {
-      var bpt = await isolate.addBreakpoint(script, LINE_A, col);
-      expect(bpt.resolved, isTrue);
-      int resolvedLine = await bpt.location.getLine();
-      int resolvedCol = await bpt.location.getColumn();
-      print('20:${col} -> ${resolvedLine}:${resolvedCol}');
-      if (col <= 12) {
-        expect(resolvedLine, equals(LINE_A));
-        expect(resolvedCol, equals(3));
-      } else if (col <= 36) {
-        expect(resolvedLine, equals(LINE_A));
-        expect(resolvedCol, equals(12));
-      } else {
-        expect(resolvedLine, equals(LINE_B));
-        expect(resolvedCol, equals(12));
-      }
-      expect((await isolate.removeBreakpoint(bpt)).type, equals('Success'));
-    }
-
-    // Make sure that a zero column is an error.
-    var caughtException = false;
-    try {
-      await isolate.addBreakpoint(script, 20, 0);
-      expect(false, isTrue, reason: 'Unreachable');
-    } on ServerRpcException catch (e) {
-      caughtException = true;
-      expect(e.code, equals(ServerRpcException.kInvalidParams));
-      expect(e.message, "addBreakpoint: invalid 'column' parameter: 0");
-    }
-    expect(caughtException, isTrue);
-  },
-];
-
-main(args) => runIsolateTests(args, tests,
-    testeeConcurrent: testMain, pause_on_start: true);
diff --git a/runtime/observatory/tests/service/collect_all_garbage_test.dart b/runtime/observatory/tests/service/collect_all_garbage_test.dart
new file mode 100644
index 0000000..8db2921
--- /dev/null
+++ b/runtime/observatory/tests/service/collect_all_garbage_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+
+import 'test_helper.dart';
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    var result = await isolate.invokeRpcNoUpgrade('_collectAllGarbage', {});
+    expect(result['type'], equals('Success'));
+  },
+];
+
+main(args) async => runIsolateTests(args, tests);
diff --git a/runtime/observatory/tests/service/coverage_const_field_test.dart b/runtime/observatory/tests/service/coverage_const_field_test.dart
new file mode 100644
index 0000000..9184a23
--- /dev/null
+++ b/runtime/observatory/tests/service/coverage_const_field_test.dart
@@ -0,0 +1,66 @@
+// 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:developer';
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const int LINE = 14;
+
+class Bar {
+  static const String field = "field"; // LINE
+}
+
+void testFunction() {
+  debugger();
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    var stack = await isolate.getStack();
+
+    // Make sure we are in the right place.
+    expect(stack.type, 'Stack');
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+    expect(stack['frames'][0].function.name, 'testFunction');
+
+    var root = isolate.rootLibrary;
+    await root.load();
+    Script script = root.scripts.first;
+    await script.load();
+
+    var params = {
+      'reports': ['Coverage'],
+      'scriptId': script.id,
+      'forceCompile': true
+    };
+    var report = await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+    List<dynamic> ranges = report['ranges'];
+
+    int match = 0;
+    for (var range in ranges) {
+      for (int i in range["coverage"]["hits"]) {
+        int line = script.tokenToLine(i);
+        if (line == null) {
+          throw FormatException('token ${i} was missing source location');
+        }
+        // Check LINE.
+        if (line == LINE) {
+          match = (match | 1);
+        } else if (line == LINE - 3) {
+          // static const field LINE is defined at LINE - 3.
+          match = (match | 2);
+        }
+      }
+    }
+    // Neither LINE nor Bar.field should be added into coverage.
+    expect(match, 0);
+  },
+  resumeIsolate
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory/tests/service/coverage_leaf_function_test.dart b/runtime/observatory/tests/service/coverage_leaf_function_test.dart
index f178426..a90ec86 100644
--- a/runtime/observatory/tests/service/coverage_leaf_function_test.dart
+++ b/runtime/observatory/tests/service/coverage_leaf_function_test.dart
@@ -44,12 +44,12 @@
 
     var expectedRange = {
       'scriptIndex': 0,
-      'startPos': ifKernel(392, 26),
-      'endPos': ifKernel(442, 38),
+      'startPos': 392,
+      'endPos': 442,
       'compiled': true,
       'coverage': {
-        'hits': ifKernel([], []),
-        'misses': ifKernel([392], [26])
+        'hits': [],
+        'misses': [392]
       }
     };
 
@@ -85,12 +85,12 @@
 
     var expectedRange = {
       'scriptIndex': 0,
-      'startPos': ifKernel(392, 26),
-      'endPos': ifKernel(442, 38),
+      'startPos': 392,
+      'endPos': 442,
       'compiled': true,
       'coverage': {
-        'hits': ifKernel([392], [26]),
-        'misses': ifKernel([], [])
+        'hits': [392],
+        'misses': []
       }
     };
 
diff --git a/runtime/observatory/tests/service/coverage_optimized_function_test.dart b/runtime/observatory/tests/service/coverage_optimized_function_test.dart
index e7a38e7..8d68907 100644
--- a/runtime/observatory/tests/service/coverage_optimized_function_test.dart
+++ b/runtime/observatory/tests/service/coverage_optimized_function_test.dart
@@ -37,12 +37,12 @@
 
     var expectedRange = {
       'scriptIndex': 0,
-      'startPos': ifKernel(469, 26),
-      'endPos': ifKernel(536, 51),
+      'startPos': 469,
+      'endPos': 536,
       'compiled': true,
       'coverage': {
-        'hits': ifKernel([469, 509, 520, 524], [26, 37, 41, 45]),
-        'misses': ifKernel([], [])
+        'hits': [469, 509, 520, 524],
+        'misses': []
       }
     };
 
diff --git a/runtime/observatory/tests/service/get_object_rpc_test.dart b/runtime/observatory/tests/service/get_object_rpc_test.dart
index 3f0ff6c..de51a71 100644
--- a/runtime/observatory/tests/service/get_object_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_object_rpc_test.dart
@@ -703,7 +703,7 @@
     expect(result['id'], startsWith('libraries/'));
     expect(result['uri'], startsWith('file:'));
     expect(result['uri'], endsWith('get_object_rpc_test.dart'));
-    expect(result['_kind'], equals(ifKernel('kernel', 'script')));
+    expect(result['_kind'], equals('kernel'));
     expect(result['library']['type'], equals('@Library'));
     expect(result['source'], startsWith('// Copyright (c)'));
     expect(result['tokenPosTable'].length, isPositive);
diff --git a/runtime/observatory/tests/service/get_source_report_test.dart b/runtime/observatory/tests/service/get_source_report_test.dart
index 7627ef3..7abd05e 100644
--- a/runtime/observatory/tests/service/get_source_report_test.dart
+++ b/runtime/observatory/tests/service/get_source_report_test.dart
@@ -73,12 +73,12 @@
 
     var expectedRange = {
       'scriptIndex': 0,
-      'startPos': ifKernel(432, 40),
-      'endPos': ifKernel(576, 89),
+      'startPos': 432,
+      'endPos': 576,
       'compiled': true,
       'coverage': {
-        'hits': ifKernel([432, 482, 533, 562], [40, 55, 73, 83]),
-        'misses': ifKernel([495], [61])
+        'hits': [432, 482, 533, 562],
+        'misses': [495],
       }
     };
 
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index 0cdbc33..ea1e417 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -20,11 +20,6 @@
 developer_extension_test: SkipByDesign
 get_isolate_after_language_error_test: SkipByDesign
 
-# Kernel version of tests
-[ $compiler != dartk ]
-add_breakpoint_rpc_kernel_test: SkipByDesign # kernel specific version of add_breakpoint_rpc_test
-evaluate_function_type_parameters_test: SkipByDesign # only supported in kernel
-
 # Service protocol is not supported in product mode.
 [ $mode == product ]
 *: SkipByDesign
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
index 4a4cf8f..316e3f2 100644
--- a/runtime/observatory/tests/service/service_kernel.status
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -3,7 +3,6 @@
 # BSD-style license that can be found in the LICENSE file.
 
 [ $compiler == app_jitk ]
-add_breakpoint_rpc_test: SkipByDesign # non-kernel specific version of add_breakpoint_rpc_kernel_test.
 async_generator_breakpoint_test: SkipByDesign # No incremental compiler available.
 bad_reload_test: RuntimeError
 break_on_activation_test: SkipByDesign # No incremental compiler available.
@@ -158,10 +157,7 @@
 simple_reload_test: RuntimeError, Timeout
 valid_source_locations_test: Pass, Slow, Timeout # Issue 34736
 
-# Kernel works slightly different. There are kernel specific versions.
-# These are the non-kernel specific versions so skip tests and allow errors.
 [ $compiler == dartk || $compiler == dartkb ]
-add_breakpoint_rpc_test: SkipByDesign # non-kernel specific version of add_breakpoint_rpc_kernel_test.
 bad_reload_test: RuntimeError # Issue 34025
 coverage_optimized_function_test: Pass, Slow
 evaluate_activation_in_method_class_test: RuntimeError # Issue 35505
diff --git a/runtime/observatory/tests/service/service_test_common.dart b/runtime/observatory/tests/service/service_test_common.dart
index 87893bc..e7f831f 100644
--- a/runtime/observatory/tests/service/service_test_common.dart
+++ b/runtime/observatory/tests/service/service_test_common.dart
@@ -579,36 +579,3 @@
   }
   return result;
 }
-
-bool isKernel() {
-  for (String argument in Platform.executableArguments) {
-    if (argument.startsWith("--no-preview_dart_2")) return false;
-    if (argument.startsWith("--no-preview-dart-2")) return false;
-  }
-  return true;
-}
-
-E ifKernel<E>(E then, E otherwise) {
-  if (isKernel()) return then;
-  return otherwise;
-}
-
-void ifKernelExecute(Function kernelFunction, Function nonKernelFunction) {
-  if (isKernel()) {
-    kernelFunction();
-  } else {
-    nonKernelFunction();
-  }
-}
-
-void nonKernelExecute(Function nonKernelFunction) {
-  if (!isKernel()) {
-    nonKernelFunction();
-  }
-}
-
-void kernelExecute(Function kernelFunction) {
-  if (isKernel()) {
-    kernelFunction();
-  }
-}
diff --git a/runtime/observatory/tests/service/yield_positions_with_finally_test.dart b/runtime/observatory/tests/service/yield_positions_with_finally_test.dart
new file mode 100644
index 0000000..af9643b
--- /dev/null
+++ b/runtime/observatory/tests/service/yield_positions_with_finally_test.dart
@@ -0,0 +1,212 @@
+// 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:developer';
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const int LINE = 106;
+const int LINE_A = 23;
+const int LINE_B = 36;
+const int LINE_C = 47;
+const int LINE_D = 61;
+const int LINE_E = 78;
+const int LINE_F = 93;
+
+// break statement
+Stream<int> testBreak() async* {
+  for (int t = 0; t < 10; t++) {
+    try {
+      if (t == 1) break;
+      await throwException(); // LINE_A
+    } catch (e) {} finally {
+      yield t;
+    }
+  }
+}
+
+// return statement
+Stream<int> testReturn() async* {
+  for (int t = 0; t < 10; t++) {
+    try {
+      yield t;
+      if (t == 1) return;
+      await throwException(); // LINE_B
+    } catch (e) {} finally {
+      yield t;
+    }
+  }
+}
+
+// Multiple functions
+Stream<int> testMultipleFunctions() async* {
+  try {
+    yield 0;
+    await throwException(); // LINE_C
+  } catch (e) {} finally {
+    yield 1;
+  }
+}
+
+// continue statement
+Stream<int> testContinueSwitch() async* {
+  int currentState = 0;
+  switch (currentState) {
+    case 0:
+      {
+        try {
+          if (currentState == 1) continue label;
+          await throwException(); // LINE_D
+        } catch (e) {} finally {
+          yield 0;
+        }
+        yield 1;
+        break;
+      }
+    label:
+    case 1:
+      break;
+  }
+}
+
+Stream<int> testNestFinally() async* {
+  int i = 0;
+  try {
+    if (i == 1) return;
+    await throwException(); //LINE_E
+  } catch (e) {} finally {
+    try {
+      yield i;
+    } finally {
+      yield 1;
+    }
+    yield 1;
+  }
+}
+
+Stream<int> testAsyncClosureInFinally() async* {
+  int i = 0;
+  try {
+    if (i == 1) return;
+    await throwException(); //LINE_F
+  } catch (e) {} finally {
+    inner() async {
+      await Future.delayed(Duration(milliseconds: 10));
+    }
+
+    await inner;
+    yield 1;
+  }
+}
+
+Future<void> throwException() async {
+  await Future.delayed(Duration(milliseconds: 10));
+  throw new Exception(""); // LINE
+}
+
+code() async {
+  await for (var x in testBreak()) {}
+  await for (var x in testReturn()) {}
+  await for (var x in testMultipleFunctions()) {}
+  await for (var x in testContinueSwitch()) {}
+  await for (var x in testNestFinally()) {}
+  await for (var x in testAsyncClosureInFinally()) {}
+}
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE),
+  (Isolate isolate) async {
+    // test break statement
+    ServiceMap stack = await isolate.getStack();
+    expect(stack['awaiterFrames'], isNotNull);
+    expect(stack['awaiterFrames'].length, greaterThanOrEqualTo(2));
+
+    // Check second top frame contains correct line number
+    Script script = stack['awaiterFrames'][1].location.script;
+    expect(script.tokenToLine(stack['awaiterFrames'][1].location.tokenPos),
+        equals(LINE_A));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE),
+  (Isolate isolate) async {
+    // test return statement
+    ServiceMap stack = await isolate.getStack();
+    expect(stack['awaiterFrames'], isNotNull);
+    expect(stack['awaiterFrames'].length, greaterThanOrEqualTo(2));
+
+    // Check second top frame contains correct line number
+    Script script = stack['awaiterFrames'][1].location.script;
+    expect(script.tokenToLine(stack['awaiterFrames'][1].location.tokenPos),
+        equals(LINE_B));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE),
+  (Isolate isolate) async {
+    // test break statement
+    ServiceMap stack = await isolate.getStack();
+    expect(stack['awaiterFrames'], isNotNull);
+    expect(stack['awaiterFrames'].length, greaterThanOrEqualTo(2));
+
+    // Check second top frame contains correct line number
+    Script script = stack['awaiterFrames'][1].location.script;
+    expect(script.tokenToLine(stack['awaiterFrames'][1].location.tokenPos),
+        equals(LINE_C));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE),
+  (Isolate isolate) async {
+    // test break statement
+    ServiceMap stack = await isolate.getStack();
+    expect(stack['awaiterFrames'], isNotNull);
+    expect(stack['awaiterFrames'].length, greaterThanOrEqualTo(2));
+
+    // Check second top frame contains correct line number
+    Script script = stack['awaiterFrames'][1].location.script;
+    expect(script.tokenToLine(stack['awaiterFrames'][1].location.tokenPos),
+        equals(LINE_D));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE),
+  (Isolate isolate) async {
+    // test nested finally statement
+    ServiceMap stack = await isolate.getStack();
+    expect(stack['awaiterFrames'], isNotNull);
+    expect(stack['awaiterFrames'].length, greaterThanOrEqualTo(2));
+
+    // Check second top frame contains correct line number
+    Script script = stack['awaiterFrames'][1].location.script;
+    expect(script.tokenToLine(stack['awaiterFrames'][1].location.tokenPos),
+        equals(LINE_E));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE),
+  (Isolate isolate) async {
+    // test async closure within finally block
+    ServiceMap stack = await isolate.getStack();
+    expect(stack['awaiterFrames'], isNotNull);
+    expect(stack['awaiterFrames'].length, greaterThanOrEqualTo(2));
+
+    // Check second top frame contains correct line number
+    Script script = stack['awaiterFrames'][1].location.script;
+    expect(script.tokenToLine(stack['awaiterFrames'][1].location.tokenPos),
+        equals(LINE_F));
+  },
+  resumeIsolate,
+  hasStoppedAtExit
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 0803ea3..2dd7547 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -605,40 +605,6 @@
 template <typename T>
 static inline void USE(T) {}
 
-// Use implicit_cast as a safe version of static_cast or const_cast
-// for upcasting in the type hierarchy (i.e. casting a pointer to Foo
-// to a pointer to SuperclassOfFoo or casting a pointer to Foo to
-// a const pointer to Foo).
-// When you use implicit_cast, the compiler checks that the cast is safe.
-// Such explicit implicit_casts are necessary in surprisingly many
-// situations where C++ demands an exact type match instead of an
-// argument type convertible to a target type.
-//
-// The From type can be inferred, so the preferred syntax for using
-// implicit_cast is the same as for static_cast etc.:
-//
-//   implicit_cast<ToType>(expr)
-//
-// implicit_cast would have been part of the C++ standard library,
-// but the proposal was submitted too late.  It will probably make
-// its way into the language in the future.
-template <typename To, typename From>
-inline To implicit_cast(From const& f) {
-  return f;
-}
-
-// Use like this: down_cast<T*>(foo);
-template <typename To, typename From>  // use like this: down_cast<T*>(foo);
-inline To down_cast(From* f) {         // so we only accept pointers
-  // Ensures that To is a sub-type of From *.  This test is here only
-  // for compile-time type checking, and has no overhead in an
-  // optimized build at run-time, as it will be optimized away completely.
-  if (false) {
-    implicit_cast<From, To>(0);
-  }
-  return static_cast<To>(f);
-}
-
 // The type-based aliasing rule allows the compiler to assume that
 // pointers of different types (for some definition of different)
 // never alias each other. Thus the following code does not work:
diff --git a/runtime/platform/growable_array.h b/runtime/platform/growable_array.h
index 75922621e..615b616 100644
--- a/runtime/platform/growable_array.h
+++ b/runtime/platform/growable_array.h
@@ -29,8 +29,34 @@
     }
   }
 
+  BaseGrowableArray(BaseGrowableArray&& other)
+      : length_(other.length_),
+        capacity_(other.capacity_),
+        data_(other.data_),
+        allocator_(other.allocator_) {
+    other.length_ = 0;
+    other.capacity_ = 0;
+    other.data_ = NULL;
+  }
+
   ~BaseGrowableArray() { allocator_->template Free<T>(data_, capacity_); }
 
+  BaseGrowableArray& operator=(BaseGrowableArray&& other) {
+    intptr_t temp = other.length_;
+    other.length_ = length_;
+    length_ = temp;
+    temp = other.capacity_;
+    other.capacity_ = capacity_;
+    capacity_ = temp;
+    T* temp_data = other.data_;
+    other.data_ = data_;
+    data_ = temp_data;
+    Allocator* temp_allocator = other.allocator_;
+    other.allocator_ = allocator_;
+    allocator_ = temp_allocator;
+    return *this;
+  }
+
   intptr_t length() const { return length_; }
   T* data() const { return data_; }
   bool is_empty() const { return length_ == 0; }
diff --git a/runtime/runtime_args.gni b/runtime/runtime_args.gni
index cf9e71d..35e6e7c 100644
--- a/runtime/runtime_args.gni
+++ b/runtime/runtime_args.gni
@@ -80,8 +80,8 @@
     dart_component_kind = "static_library"
   }
 
-  # Whether the VM's platform dill file contains bytecode.
-  dart_platform_bytecode = false
+  # Controls whether the VM uses bytecode.
+  dart_platform_bytecode = true
 
   # Whether the VM includes the kernel service in all modes (debug, release,
   # product).
@@ -89,6 +89,9 @@
 
   # Whether libdart should export the symbols of the Dart API.
   dart_lib_export_symbols = true
+
+  # Whether dart:wasm should be enabled.
+  dart_enable_wasm = false
 }
 
 declare_args() {
diff --git a/runtime/tests/vm/dart/regress_38182_test.dart b/runtime/tests/vm/dart/regress_38182_test.dart
new file mode 100644
index 0000000..952bee4
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_38182_test.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.
+
+// VMOptions=--stacktrace_every=1 --deterministic
+
+void foo1(par) {
+  try {
+    () {
+      // The parameter `par` has to be captured within a closure, but it doesn't
+      // matter whether or not it's actually used.
+      print(par.runtimeType);
+    };
+    // We need to throw, otherwise the crash doesn't happen. We don't need to
+    // catch it explicitly, however.
+    throw '';
+  } finally {
+    // We need to trigger a lot of stack overflow checks. Somewhere around
+    // 20000 seems to work.
+    int x = 0;
+    for (int loc1 = 0; loc1 < 20000; loc1++) {
+      x += loc1;
+    }
+    print(x);
+  }
+}
+
+main() {
+  try {
+    // Parameter isn't important.
+    foo1(null);
+  } catch (e) {
+    print('foo1 threw');
+  }
+}
diff --git a/runtime/tests/vm/dart/regress_merge_blocks_with_phis_test.dart b/runtime/tests/vm/dart/regress_merge_blocks_with_phis_test.dart
index a3edcce..606e4c5 100644
--- a/runtime/tests/vm/dart/regress_merge_blocks_with_phis_test.dart
+++ b/runtime/tests/vm/dart/regress_merge_blocks_with_phis_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 //
-// VMOptions=--deterministic --optimization-counter-threshold=5 --use-bytecode-compiler
+// VMOptions=--optimization-counter-threshold=5 --use-bytecode-compiler
 //
 // Test that block merging takes phis into account.
 //
diff --git a/runtime/tests/vm/dart/run_appended_aot_snapshot_test.dart b/runtime/tests/vm/dart/run_appended_aot_snapshot_test.dart
new file mode 100644
index 0000000..b0b2736
--- /dev/null
+++ b/runtime/tests/vm/dart/run_appended_aot_snapshot_test.dart
@@ -0,0 +1,74 @@
+// 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:typed_data';
+
+import "package:path/path.dart" as path;
+
+import "snapshot_test_helper.dart";
+
+final appSnapshotPageSize = 4096;
+const appjitMagicNumber = <int>[0xdc, 0xdc, 0xf6, 0xf6, 0, 0, 0, 0];
+
+Future writeAppendedExecutable(runtimePath, payloadPath, outputPath) async {
+  final runtime = File(runtimePath);
+  final int runtimeLength = runtime.lengthSync();
+
+  final padding = (appSnapshotPageSize - (runtimeLength % appSnapshotPageSize));
+  final padBytes = new List<int>.filled(padding, 0);
+  final offset = runtimeLength + padding;
+
+  final offsetBytes = new ByteData(8) // 64 bit in bytes.
+    ..setUint64(0, offset, Endian.little);
+
+  final outputFile = File(outputPath).openWrite();
+  outputFile.add(runtime.readAsBytesSync());
+  outputFile.add(padBytes);
+  outputFile.add(File(payloadPath).readAsBytesSync());
+  outputFile.add(offsetBytes.buffer.asUint8List());
+  outputFile.add(appjitMagicNumber);
+  await outputFile.close();
+}
+
+Future<void> main(List<String> args) async {
+  if (args.length == 1 && args[0] == "--child") {
+    print("Hello, Appended AOT");
+    return;
+  }
+
+  await withTempDir((String tmp) async {
+    final String dillPath = path.join(tmp, "test.dill");
+    final String aotPath = path.join(tmp, "test.aot");
+    final String exePath = path.join(tmp, "test.exe");
+
+    final dillResult = await runGenKernel("generate dill", [
+      "--aot",
+      "-o",
+      dillPath,
+      "runtime/tests/vm/dart/run_appended_aot_snapshot_test.dart",
+    ]);
+    expectOutput("", dillResult);
+
+    final aotResult = await runGenSnapshot("generate aot", [
+      "--snapshot-kind=app-aot-blobs",
+      "--blobs_container_filename=$aotPath",
+      dillPath,
+    ]);
+    expectOutput("", aotResult);
+
+    await writeAppendedExecutable(dartPrecompiledRuntime, aotPath, exePath);
+
+    if (Platform.isLinux || Platform.isMacOS) {
+      final execResult =
+          await runBinary("make executable", "chmod", ["+x", exePath]);
+      expectOutput("", execResult);
+    }
+
+    final runResult =
+        await runBinary("run appended aot snapshot", exePath, ["--child"]);
+    expectOutput("Hello, Appended AOT", runResult);
+  });
+}
diff --git a/runtime/tests/vm/dart/snapshot_test_helper.dart b/runtime/tests/vm/dart/snapshot_test_helper.dart
index 5c63da1..6f42b07 100644
--- a/runtime/tests/vm/dart/snapshot_test_helper.dart
+++ b/runtime/tests/vm/dart/snapshot_test_helper.dart
@@ -46,8 +46,11 @@
 final String buildDir = p.dirname(Platform.executable);
 final String platformDill = p.join(buildDir, "vm_platform_strong.dill");
 final String genSnapshot = p.join(buildDir, "gen_snapshot${executableSuffix}");
-final String genKernel =
-    p.join("pkg", "vm", "tool", "gen_kernel${scriptSuffix}");
+final String dartPrecompiledRuntime =
+    p.join(buildDir, "dart_precompiled_runtime${executableSuffix}");
+final String genKernel = p.join("pkg", "vm", "bin", "gen_kernel.dart");
+final String checkedInDartVM =
+    p.join("tools", "sdks", "dart-sdk", "bin", "dart${executableSuffix}");
 
 Future<Result> runDart(String prefix, List<String> arguments) {
   final augmentedArguments = <String>[]
@@ -58,10 +61,11 @@
 
 Future<Result> runGenKernel(String prefix, List<String> arguments) {
   final augmentedArguments = <String>[]
+    ..add(genKernel)
     ..add("--platform")
     ..add(platformDill)
     ..addAll(arguments);
-  return runBinary(prefix, genKernel, augmentedArguments);
+  return runBinary(prefix, checkedInDartVM, augmentedArguments);
 }
 
 Future<Result> runGenSnapshot(String prefix, List<String> arguments) {
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 22c5b32..d653126 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -231,6 +231,9 @@
 [ $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 ]
+dart/run_appended_aot_snapshot_test: SkipByDesign # Tests the precompiled runtime.
+
 [ $compiler == dart2analyzer || $compiler == dart2js ]
 dart/data_uri*test: Skip # Data uri's not supported by dart2js or the analyzer.
 
diff --git a/runtime/tools/dartfuzz/README.md b/runtime/tools/dartfuzz/README.md
index 0002b65..35accd4 100644
--- a/runtime/tools/dartfuzz/README.md
+++ b/runtime/tools/dartfuzz/README.md
@@ -51,7 +51,7 @@
     --dart-top        : sets DART_TOP explicitly through command line
     --mode1           : m1
     --mode2           : m2, and values one of
-        jit-[debug-][ia32|x64|arm32|arm64|dbc32|dbc64]   = Dart JIT
+        jit-[debug-][ia32|x64|arm32|arm64]               = Dart JIT
         aot-[debug-][x64|arm32|arm64]                    = Dart AOT
         kbc-[int|mix|cmp]-[debug-][ia32|x64|arm32|arm64] = Dart KBC
                                                            (interpreted/
diff --git a/runtime/tools/dartfuzz/dartfuzz.dart b/runtime/tools/dartfuzz/dartfuzz.dart
index 8a02ff3..ba9b779 100644
--- a/runtime/tools/dartfuzz/dartfuzz.dart
+++ b/runtime/tools/dartfuzz/dartfuzz.dart
@@ -14,12 +14,18 @@
 // 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.42';
+const String version = '1.49';
 
 // Restriction on statements and expressions.
-const int stmtLength = 2;
 const int stmtDepth = 1;
 const int exprDepth = 2;
+const int numStatements = 2;
+const int numGlobalVars = 4;
+const int numLocalVars = 4;
+const int numGlobalMethods = 4;
+const int numClassMethods = 3;
+const int numMethodParams = 4;
+const int numClasses = 4;
 
 // Naming conventions.
 const varName = 'var';
@@ -28,6 +34,32 @@
 const fieldName = 'fld';
 const methodName = 'foo';
 
+// Class that tracks the state of the filter applied to the
+// right-hand-side of an assignment in order to avoid generating
+// left-hand-side variables.
+class RhsFilter {
+  RhsFilter(this._remaining, this.lhsVar);
+  factory RhsFilter.fromDartType(DartType tp, String lhsVar) {
+    if (tp == DartType.STRING ||
+        tp == DartType.INT_LIST ||
+        tp == DartType.INT_SET ||
+        tp == DartType.INT_STRING_MAP) {
+      return RhsFilter(1, lhsVar);
+    }
+    return null;
+  }
+  // Clone the current RhsFilter instance and set remaining to 0.
+  // This is used for parameter expressions.
+  factory RhsFilter.cloneEmpty(RhsFilter rhsFilter) =>
+      rhsFilter == null ? null : RhsFilter(0, rhsFilter.lhsVar);
+  void consume() => _remaining--;
+  bool get shouldFilter => _remaining <= 0;
+  // Number of times the lhs variable can still be used on the rhs.
+  int _remaining;
+  // The name of the lhs variable to be filtered from the rhs.
+  final String lhsVar;
+}
+
 /// Class that specifies the api for calling library and ffi functions (if
 /// enabled).
 class DartApi {
@@ -97,16 +129,22 @@
     // Setup the types.
     localVars = <DartType>[];
     iterVars = <String>[];
-    globalVars = fillTypes1();
+
+    globalVars = fillTypes1(limit: numGlobalVars);
     globalVars.addAll(DartType.allTypes); // always one each
-    globalMethods = fillTypes2();
-    classFields = fillTypes2(limit: 8);
-    classMethods = fillTypes3(classFields.length);
+    globalMethods =
+        fillTypes2(limit2: numGlobalMethods, limit1: numMethodParams);
+    classFields = fillTypes2(limit2: numClasses, limit1: numLocalVars);
+    classMethods = fillTypes3(classFields.length,
+        limit2: numClassMethods, limit1: numMethodParams);
+
+    virtualClassMethods = <Map<int, List<int>>>[];
     classParents = <int>[];
     // Setup optional ffi methods and types.
     final ffiStatus = <bool>[for (final _ in globalMethods) false];
     if (ffi) {
-      List<List<DartType>> globalMethodsFfi = fillTypes2(isFfi: true);
+      List<List<DartType>> globalMethodsFfi = fillTypes2(
+          limit2: numGlobalMethods, limit1: numMethodParams, isFfi: true);
       for (var m in globalMethodsFfi) {
         globalMethods.add(m);
         ffiStatus.add(true);
@@ -214,14 +252,17 @@
   void emitVirtualMethods() {
     final currentClassTmp = currentClass;
     int parentClass = classParents[currentClass];
+    final vcm = <int, List<int>>{};
     // Chase randomly up in class hierarchy.
     while (parentClass >= 0) {
+      vcm[parentClass] = <int>[];
       for (int j = 0, n = classMethods[parentClass].length; j < n; j++) {
         if (rand.nextInt(8) == 0) {
           currentClass = parentClass;
           currentMethod = j;
           emitMethod('$methodName${parentClass}_', j,
               classMethods[parentClass][j], false);
+          vcm[parentClass].add(currentMethod);
           currentMethod = null;
           currentClass = null;
         }
@@ -233,6 +274,7 @@
       }
     }
     currentClass = currentClassTmp;
+    virtualClassMethods.add(vcm);
   }
 
   void emitClasses() {
@@ -296,6 +338,27 @@
     }
   }
 
+  void emitTryCatchFinally(Function tryBody, Function catchBody,
+      {Function finallyBody}) {
+    emitLn('try {');
+    indent += 2;
+    emitLn("", newline: false);
+    tryBody();
+    emit(";", newline: true);
+    indent -= 2;
+    emitLn('} catch (e, st) {');
+    indent += 2;
+    catchBody();
+    indent -= 2;
+    if (finallyBody != null) {
+      emitLn('} finally {');
+      indent += 2;
+      finallyBody();
+      indent -= 2;
+    }
+    emitLn('}');
+  }
+
   void emitMain() {
     emitLn('main() {');
     indent += 2;
@@ -304,53 +367,51 @@
 
     // Call each global method once.
     for (int i = 0; i < globalMethods.length; i++) {
-      emitLn('try {');
-      indent += 2;
-      emitLn("", newline: false);
-      emitCall(1, "$methodName${i}", globalMethods[i]);
-      emit(";", newline: true);
-      indent -= 2;
-      emitLn('} catch (exception, stackTrace) {');
-      indent += 2;
-      emitLn("print('$methodName$i throws');");
-      indent -= 2;
-      emitLn('}');
+      emitTryCatchFinally(() {
+        emitCall(1, "$methodName${i}", globalMethods[i]);
+      }, () {
+        emitLn("print('$methodName$i throws');");
+      });
     }
 
     // Call each class method once.
     for (int i = 0; i < classMethods.length; i++) {
       for (int j = 0; j < classMethods[i].length; j++) {
-        emitLn('try {');
-        indent += 2;
-        emitLn("", newline: false);
-        emitCall(1, "X${i}().$methodName${i}_${j}", classMethods[i][j]);
-        emit(";", newline: true);
-        indent -= 2;
-        emitLn('} catch (exception, stackTrace) {');
-        indent += 2;
-        emitLn("print('X${i}().$methodName${i}_${j}() throws');");
-        indent -= 2;
-        emitLn('}');
+        emitTryCatchFinally(() {
+          emitCall(1, "X${i}().$methodName${i}_${j}", classMethods[i][j]);
+        }, () {
+          emitLn("print('X${i}().$methodName${i}_${j}() throws');");
+        });
+      }
+      // Call each virtual class method once.
+      int parentClass = classParents[i];
+      while (parentClass >= 0) {
+        if (virtualClassMethods[i].containsKey(parentClass)) {
+          for (int j = 0; j < virtualClassMethods[i][parentClass].length; j++) {
+            emitTryCatchFinally(() {
+              emitCall(1, "X${i}().$methodName${parentClass}_${j}",
+                  classMethods[parentClass][j]);
+            }, () {
+              emitLn(
+                  "print('X${i}().$methodName${parentClass}_${j}() throws');");
+            });
+          }
+        }
+        parentClass = classParents[parentClass];
       }
     }
 
-    emitLn('try {');
-    indent += 2;
-    emitLn('X${classFields.length - 1}().run();');
-    indent -= 2;
-    emitLn('} catch (exception, stackTrace) {');
-    indent += 2;
-    emitLn("print('X${classFields.length - 1}().run() throws');");
-    indent -= 2;
-    emitLn('} finally {');
-    indent += 2;
-    emitLn("print('", newline: false);
-    for (int i = 0; i < globalVars.length; i++) {
-      emit('\$$varName$i\\n');
-    }
-    emit("');", newline: true);
-    indent -= 2;
-    emitLn('}');
+    emitTryCatchFinally(() {
+      emit('X${classFields.length - 1}().run()');
+    }, () {
+      emitLn("print('X${classFields.length - 1}().run() throws');");
+    }, finallyBody: () {
+      emitLn("print('", newline: false);
+      for (int i = 0; i < globalVars.length; i++) {
+        emit('\$$varName$i\\n');
+      }
+      emit("');", newline: true);
+    });
     indent -= 2;
     emitLn('}');
   }
@@ -415,9 +476,13 @@
   bool emitAssign() {
     DartType tp = getType();
     emitLn('', newline: false);
-    emitVar(0, tp, isLhs: true);
-    emitAssignOp(tp);
-    emitExpr(0, tp);
+    final emittedVar = emitVar(0, tp, isLhs: true);
+    RhsFilter rhsFilter = RhsFilter.fromDartType(tp, emittedVar);
+    final assignOp = emitAssignOp(tp);
+    if ({'*=', '+='}.contains(assignOp)) {
+      rhsFilter?.consume();
+    }
+    emitExpr(0, tp, rhsFilter: rhsFilter);
     emit(';', newline: true);
     return true;
   }
@@ -504,7 +569,9 @@
   bool emitForIn(int depth) {
     final int i = localVars.length;
     emitLn('for (int $localName$i in ', newline: false);
+    localVars.add(null); // declared, but don't use
     emitExpr(0, rand.nextBool() ? DartType.INT_LIST : DartType.INT_SET);
+    localVars.removeLast(); // will get type
     emit(') {', newline: true);
     indent += 2;
     nest++;
@@ -520,10 +587,11 @@
   // Emit a simple membership forEach loop.
   bool emitForEach(int depth) {
     final int i = localVars.length;
+    final int j = i + 1;
     emitLn("", newline: false);
     final emittedVar = emitScalarVar(DartType.INT_STRING_MAP, isLhs: false);
     iterVars.add(emittedVar);
-    emit('.forEach(($localName$i, $localName${i + 1}) {\n');
+    emit('.forEach(($localName$i, $localName$j) {\n');
     indent += 2;
     final int nestTmp = nest;
     // Reset, since forEach cannot break out of own or enclosing context.
@@ -628,8 +696,11 @@
   // Emit a new program scope that introduces a new local variable.
   bool emitScope(int depth) {
     DartType tp = getType();
-    emitLn('{ ${tp.name} $localName${localVars.length} = ', newline: false);
+    final int i = localVars.length;
+    emitLn('{ ${tp.name} $localName$i = ', newline: false);
+    localVars.add(null); // declared, but don't use
     emitExpr(0, tp);
+    localVars.removeLast(); // will get type
     emit(';', newline: true);
     indent += 2;
     localVars.add(tp);
@@ -709,7 +780,7 @@
 
   // Emit statements. Returns true if code may fall-through.
   bool emitStatements(int depth) {
-    int s = 1 + rand.nextInt(stmtLength);
+    int s = 1 + rand.nextInt(numStatements);
     for (int i = 0; i < s; i++) {
       if (!emitStatement(depth)) {
         return false; // rest would be dead code
@@ -726,8 +797,8 @@
     emit(rand.nextInt(2) == 0 ? 'true' : 'false');
   }
 
-  void emitSmallPositiveInt() {
-    emit('${rand.nextInt(100)}');
+  void emitSmallPositiveInt({int limit = 100}) {
+    emit('${rand.nextInt(limit)}');
   }
 
   void emitSmallNegativeInt() {
@@ -778,25 +849,25 @@
     emit("'");
   }
 
-  void emitElementExpr(int depth, DartType tp) {
+  void emitElementExpr(int depth, DartType tp, {RhsFilter rhsFilter}) {
     if (currentMethod != null) {
-      emitExpr(depth, tp);
+      emitExpr(depth, tp, rhsFilter: rhsFilter);
     } else {
-      emitLiteral(depth, tp);
+      emitLiteral(depth, tp, rhsFilter: rhsFilter);
     }
   }
 
-  void emitElement(int depth, DartType tp) {
+  void emitElement(int depth, DartType tp, {RhsFilter rhsFilter}) {
     if (tp == DartType.INT_STRING_MAP) {
       emitSmallPositiveInt();
       emit(' : ');
-      emitElementExpr(depth, DartType.STRING);
+      emitElementExpr(depth, DartType.STRING, rhsFilter: rhsFilter);
     } else {
-      emitElementExpr(depth, DartType.INT);
+      emitElementExpr(depth, DartType.INT, rhsFilter: rhsFilter);
     }
   }
 
-  void emitCollectionElement(int depth, DartType tp) {
+  void emitCollectionElement(int depth, DartType tp, {RhsFilter rhsFilter}) {
     int r = depth <= exprDepth ? rand.nextInt(10) : 10;
     switch (r) {
       // Favors elements over control-flow collections.
@@ -804,19 +875,19 @@
         // TODO (ajcbik): Remove restriction once compiler is fixed.
         if (depth < 2) {
           emit('...'); // spread
-          emitCollection(depth + 1, tp);
+          emitCollection(depth + 1, tp, rhsFilter: rhsFilter);
         } else {
-          emitElement(depth, tp);
+          emitElement(depth, tp, rhsFilter: rhsFilter);
         }
         break;
       case 1:
         emit('if (');
-        emitElementExpr(depth + 1, DartType.BOOL);
+        emitElementExpr(depth + 1, DartType.BOOL, rhsFilter: rhsFilter);
         emit(') ');
-        emitCollectionElement(depth + 1, tp);
+        emitCollectionElement(depth + 1, tp, rhsFilter: rhsFilter);
         if (rand.nextBool()) {
           emit(' else ');
-          emitCollectionElement(depth + 1, tp);
+          emitCollectionElement(depth + 1, tp, rhsFilter: rhsFilter);
         }
         break;
       case 2:
@@ -824,40 +895,45 @@
           final int i = localVars.length;
           emit('for (int $localName$i ');
           // For-loop (induction, list, set).
+          localVars.add(null); // declared, but don't use
           switch (rand.nextInt(3)) {
             case 0:
               emit('= 0; $localName$i < ');
-              emitSmallPositiveInt();
+              emitSmallPositiveInt(limit: 16);
               emit('; $localName$i++) ');
               break;
             case 1:
               emit('in ');
-              emitCollection(depth + 1, DartType.INT_LIST);
+              emitCollection(depth + 1, DartType.INT_LIST,
+                  rhsFilter: rhsFilter);
               emit(') ');
               break;
             default:
               emit('in ');
-              emitCollection(depth + 1, DartType.INT_SET);
+              emitCollection(depth + 1, DartType.INT_SET, rhsFilter: rhsFilter);
               emit(') ');
               break;
           }
+          localVars.removeLast(); // will get type
           nest++;
+          iterVars.add("$localName$i");
           localVars.add(DartType.INT);
-          emitCollectionElement(depth + 1, tp);
+          emitCollectionElement(depth + 1, tp, rhsFilter: rhsFilter);
           localVars.removeLast();
+          iterVars.removeLast();
           nest--;
           break;
         }
       default:
-        emitElement(depth, tp);
+        emitElement(depth, tp, rhsFilter: rhsFilter);
         break;
     }
   }
 
-  void emitCollection(int depth, DartType tp) {
+  void emitCollection(int depth, DartType tp, {RhsFilter rhsFilter}) {
     emit(tp == DartType.INT_LIST ? '[ ' : '{ ');
     for (int i = 0, n = 1 + rand.nextInt(8); i < n; i++) {
-      emitCollectionElement(depth, tp);
+      emitCollectionElement(depth, tp, rhsFilter: rhsFilter);
       if (i != (n - 1)) {
         emit(', ');
       }
@@ -865,7 +941,8 @@
     emit(tp == DartType.INT_LIST ? ' ]' : ' }');
   }
 
-  void emitLiteral(int depth, DartType tp, {bool smallPositiveValue = false}) {
+  void emitLiteral(int depth, DartType tp,
+      {bool smallPositiveValue = false, RhsFilter rhsFilter}) {
     if (tp == DartType.BOOL) {
       emitBool();
     } else if (tp == DartType.INT) {
@@ -881,13 +958,13 @@
     } else if (tp == DartType.INT_LIST ||
         tp == DartType.INT_SET ||
         tp == DartType.INT_STRING_MAP) {
-      emitCollection(depth, tp);
+      emitCollection(depth, tp, rhsFilter: RhsFilter.cloneEmpty(rhsFilter));
     } else {
       assert(false);
     }
   }
 
-  String emitScalarVar(DartType tp, {bool isLhs = false}) {
+  String emitScalarVar(DartType tp, {bool isLhs = false, RhsFilter rhsFilter}) {
     // Collect all choices from globals, fields, locals, and parameters.
     Set<String> choices = <String>{};
     for (int i = 0; i < globalVars.length; i++) {
@@ -918,55 +995,84 @@
         }
       }
     }
+    // Filter out the current lhs of the expression to avoid recursive
+    // assignments of the form x = x * x.
+    if (rhsFilter != null && rhsFilter.shouldFilter) {
+      Set<String> cleanChoices = choices.difference({rhsFilter.lhsVar});
+      // If we have other choices of variables, use those.
+      if (cleanChoices.isNotEmpty) {
+        choices = cleanChoices;
+      } else if (!isLhs) {
+        // If we are emitting an RHS variable, we can emit a terminal.
+        // note that if the variable type is a collection, this might
+        // still result in a recursion.
+        emitLiteral(0, tp);
+        return null;
+      }
+      // Otherwise we have to risk creating a recursion.
+    }
     // Then pick one.
-    assert(choices.isNotEmpty);
+    if (choices.isEmpty) {
+      throw 'No variable to emit for type ${tp.name}';
+    }
     final emittedVar = '${choices.elementAt(rand.nextInt(choices.length))}';
+    if (rhsFilter != null && (emittedVar == rhsFilter.lhsVar)) {
+      rhsFilter.consume();
+    }
     emit(emittedVar);
     return emittedVar;
   }
 
-  void emitSubscriptedVar(int depth, DartType tp, {bool isLhs = false}) {
+  String emitSubscriptedVar(int depth, DartType tp,
+      {bool isLhs = false, RhsFilter rhsFilter}) {
+    String ret;
     if (tp == DartType.INT) {
-      emitScalarVar(DartType.INT_LIST, isLhs: isLhs);
+      ret =
+          emitScalarVar(DartType.INT_LIST, isLhs: isLhs, rhsFilter: rhsFilter);
       emit('[');
       emitExpr(depth + 1, DartType.INT);
       emit(']');
     } else if (tp == DartType.STRING) {
-      emitScalarVar(DartType.INT_STRING_MAP, isLhs: isLhs);
+      ret = emitScalarVar(DartType.INT_STRING_MAP,
+          isLhs: isLhs, rhsFilter: rhsFilter);
       emit('[');
       emitExpr(depth + 1, DartType.INT);
       emit(']');
     } else {
-      emitScalarVar(tp, isLhs: isLhs); // resort to scalar
+      ret = emitScalarVar(tp,
+          isLhs: isLhs, rhsFilter: rhsFilter); // resort to scalar
     }
+    return ret;
   }
 
-  void emitVar(int depth, DartType tp, {bool isLhs = false}) {
+  String emitVar(int depth, DartType tp,
+      {bool isLhs = false, RhsFilter rhsFilter}) {
     switch (rand.nextInt(2)) {
       case 0:
-        emitScalarVar(tp, isLhs: isLhs);
+        return emitScalarVar(tp, isLhs: isLhs, rhsFilter: rhsFilter);
         break;
       default:
-        emitSubscriptedVar(depth, tp, isLhs: isLhs);
+        return emitSubscriptedVar(depth, tp,
+            isLhs: isLhs, rhsFilter: rhsFilter);
         break;
     }
   }
 
-  void emitTerminal(int depth, DartType tp) {
+  void emitTerminal(int depth, DartType tp, {RhsFilter rhsFilter}) {
     switch (rand.nextInt(2)) {
       case 0:
-        emitLiteral(depth, tp);
+        emitLiteral(depth, tp, rhsFilter: rhsFilter);
         break;
       default:
-        emitVar(depth, tp);
+        emitVar(depth, tp, rhsFilter: rhsFilter);
         break;
     }
   }
 
-  void emitExprList(int depth, List<DartType> proto) {
+  void emitExprList(int depth, List<DartType> proto, {RhsFilter rhsFilter}) {
     emit('(');
     for (int i = 1; i < proto.length; i++) {
-      emitExpr(depth, proto[i]);
+      emitExpr(depth, proto[i], rhsFilter: rhsFilter);
       if (i != (proto.length - 1)) {
         emit(', ');
       }
@@ -975,62 +1081,52 @@
   }
 
   // Emit expression with unary operator: (~(x))
-  void emitUnaryExpr(int depth, DartType tp) {
+  void emitUnaryExpr(int depth, DartType tp, {RhsFilter rhsFilter}) {
     if (tp == DartType.BOOL || tp == DartType.INT || tp == DartType.DOUBLE) {
       emit('(');
       emitUnaryOp(tp);
       emit('(');
-      emitExpr(depth + 1, tp);
+      emitExpr(depth + 1, tp, rhsFilter: rhsFilter);
       emit('))');
     } else {
-      emitTerminal(depth, tp); // resort to terminal
+      emitTerminal(depth, tp, rhsFilter: rhsFilter); // resort to terminal
     }
   }
 
   // Emit expression with binary operator: (x + y)
-  void emitBinaryExpr(int depth, DartType tp) {
+  void emitBinaryExpr(int depth, DartType tp, {RhsFilter rhsFilter}) {
     if (tp == DartType.BOOL) {
       // For boolean, allow type switch with relational op.
       if (rand.nextInt(2) == 0) {
         DartType deeper_tp = getType();
         emit('(');
-        emitExpr(depth + 1, deeper_tp);
+        emitExpr(depth + 1, deeper_tp, rhsFilter: rhsFilter);
         emitRelOp(deeper_tp);
-        emitExpr(depth + 1, deeper_tp);
+        emitExpr(depth + 1, deeper_tp, rhsFilter: rhsFilter);
         emit(')');
         return;
       }
-    } else if (tp == DartType.STRING || tp == DartType.INT_LIST) {
-      // For strings and lists, a construct like x = x + x; inside a loop
-      // yields an exponentially growing data structure. We avoid this
-      // situation by forcing a literal on the rhs of each +.
-      emit('(');
-      emitExpr(depth + 1, tp);
-      emitBinaryOp(tp);
-      emitLiteral(depth + 1, tp);
-      emit(')');
-      return;
     }
     emit('(');
-    emitExpr(depth + 1, tp);
+    emitExpr(depth + 1, tp, rhsFilter: rhsFilter);
     emitBinaryOp(tp);
-    emitExpr(depth + 1, tp);
+    emitExpr(depth + 1, tp, rhsFilter: rhsFilter);
     emit(')');
   }
 
   // Emit expression with ternary operator: (b ? x : y)
-  void emitTernaryExpr(int depth, DartType tp) {
+  void emitTernaryExpr(int depth, DartType tp, {RhsFilter rhsFilter}) {
     emit('(');
-    emitExpr(depth + 1, DartType.BOOL);
+    emitExpr(depth + 1, DartType.BOOL, rhsFilter: rhsFilter);
     emit(' ? ');
-    emitExpr(depth + 1, tp);
+    emitExpr(depth + 1, tp, rhsFilter: rhsFilter);
     emit(' : ');
-    emitExpr(depth + 1, tp);
+    emitExpr(depth + 1, tp, rhsFilter: rhsFilter);
     emit(')');
   }
 
   // Emit expression with pre/post-increment/decrement operator: (x++)
-  void emitPreOrPostExpr(int depth, DartType tp) {
+  void emitPreOrPostExpr(int depth, DartType tp, {RhsFilter rhsFilter}) {
     if (tp == DartType.INT) {
       int r = rand.nextInt(2);
       emit('(');
@@ -1039,18 +1135,18 @@
       if (r == 1) emitPreOrPostOp(tp);
       emit(')');
     } else {
-      emitTerminal(depth, tp); // resort to terminal
+      emitTerminal(depth, tp, rhsFilter: rhsFilter); // resort to terminal
     }
   }
 
   // Emit library call.
-  void emitLibraryCall(int depth, DartType tp) {
+  void emitLibraryCall(int depth, DartType tp, {RhsFilter rhsFilter}) {
     DartLib lib = getLibraryMethod(tp);
     final String proto = lib.proto;
     // Receiver.
     if (proto[0] != 'V') {
       emit('(');
-      emitArg(depth + 1, proto[0]);
+      emitArg(depth + 1, proto[0], rhsFilter: rhsFilter);
       emit(').');
     }
     // Call.
@@ -1060,7 +1156,7 @@
       emit('(');
       if (proto[1] != 'V') {
         for (int i = 1; i < proto.length; i++) {
-          emitArg(depth + 1, proto[i]);
+          emitArg(depth + 1, proto[i], rhsFilter: rhsFilter);
           if (i != (proto.length - 1)) {
             emit(', ');
           }
@@ -1071,17 +1167,19 @@
   }
 
   // Emit call to a specific method.
-  void emitCall(int depth, String name, List<DartType> proto) {
+  void emitCall(int depth, String name, List<DartType> proto,
+      {RhsFilter rhsFilter}) {
     emit(name);
-    emitExprList(depth + 1, proto);
+    emitExprList(depth + 1, proto, rhsFilter: rhsFilter);
   }
 
   // Helper for a method call.
   bool pickedCall(
-      int depth, DartType tp, String name, List<List<DartType>> protos, int m) {
+      int depth, DartType tp, String name, List<List<DartType>> protos, int m,
+      {RhsFilter rhsFilter}) {
     for (int i = m - 1; i >= 0; i--) {
       if (tp == protos[i][0]) {
-        emitCall(depth + 1, "$name$i", protos[i]);
+        emitCall(depth + 1, "$name$i", protos[i], rhsFilter: rhsFilter);
         return true;
       }
     }
@@ -1089,12 +1187,13 @@
   }
 
   // Emit method call within the program.
-  void emitMethodCall(int depth, DartType tp) {
+  void emitMethodCall(int depth, DartType tp, {RhsFilter rhsFilter}) {
     // Only call backward to avoid infinite recursion.
     if (currentClass == null) {
       // Outside a class but inside a method: call backward in global methods.
       if (currentMethod != null &&
-          pickedCall(depth, tp, methodName, globalMethods, currentMethod)) {
+          pickedCall(depth, tp, methodName, globalMethods, currentMethod,
+              rhsFilter: rhsFilter)) {
         return;
       }
     } else {
@@ -1121,43 +1220,44 @@
       }
       final int m2 = globalMethods.length;
       if (pickedCall(depth, tp, '$methodName${classIndex}_',
-              classMethods[classIndex], m1) ||
-          pickedCall(depth, tp, methodName, globalMethods, m2)) {
+              classMethods[classIndex], m1, rhsFilter: rhsFilter) ||
+          pickedCall(depth, tp, methodName, globalMethods, m2,
+              rhsFilter: rhsFilter)) {
         return;
       }
     }
-    emitTerminal(depth, tp); // resort to terminal.
+    emitTerminal(depth, tp, rhsFilter: rhsFilter); // resort to terminal.
   }
 
   // Emit expression.
-  void emitExpr(int depth, DartType tp) {
+  void emitExpr(int depth, DartType tp, {RhsFilter rhsFilter}) {
     // Continuing nested expressions becomes less likely as the depth grows.
     if (rand.nextInt(depth + 1) > exprDepth) {
-      emitTerminal(depth, tp);
+      emitTerminal(depth, tp, rhsFilter: rhsFilter);
       return;
     }
     // Possibly nested expression.
     switch (rand.nextInt(7)) {
       case 0:
-        emitUnaryExpr(depth, tp);
+        emitUnaryExpr(depth, tp, rhsFilter: rhsFilter);
         break;
       case 1:
-        emitBinaryExpr(depth, tp);
+        emitBinaryExpr(depth, tp, rhsFilter: rhsFilter);
         break;
       case 2:
-        emitTernaryExpr(depth, tp);
+        emitTernaryExpr(depth, tp, rhsFilter: rhsFilter);
         break;
       case 3:
-        emitPreOrPostExpr(depth, tp);
+        emitPreOrPostExpr(depth, tp, rhsFilter: rhsFilter);
         break;
       case 4:
-        emitLibraryCall(depth, tp);
+        emitLibraryCall(depth, tp, rhsFilter: RhsFilter.cloneEmpty(rhsFilter));
         break;
       case 5:
-        emitMethodCall(depth, tp);
+        emitMethodCall(depth, tp, rhsFilter: RhsFilter.cloneEmpty(rhsFilter));
         break;
       default:
-        emitTerminal(depth, tp);
+        emitTerminal(depth, tp, rhsFilter: rhsFilter);
         break;
     }
   }
@@ -1167,9 +1267,9 @@
   //
 
   // Emit same type in-out assignment operator.
-  void emitAssignOp(DartType tp) {
+  String emitAssignOp(DartType tp) {
     if (tp == DartType.INT) {
-      emit(oneOf(const <String>[
+      final assignOp = oneOf(const <String>[
         ' += ',
         ' -= ',
         ' *= ',
@@ -1182,12 +1282,18 @@
         ' <<= ',
         ' ??= ',
         ' = '
-      ]));
+      ]);
+      emit(assignOp);
+      return assignOp;
     } else if (tp == DartType.DOUBLE) {
-      emit(oneOf(
-          const <String>[' += ', ' -= ', ' *= ', ' /= ', ' ??= ', ' = ']));
+      final assignOp =
+          oneOf(const <String>[' += ', ' -= ', ' *= ', ' /= ', ' ??= ', ' = ']);
+      emit(assignOp);
+      return assignOp;
     } else {
-      emit(oneOf(const <String>[' ??= ', ' = ']));
+      final assignOp = oneOf(const <String>[' ??= ', ' = ']);
+      emit(assignOp);
+      return assignOp;
     }
   }
 
@@ -1274,7 +1380,7 @@
   }
 
   // Emit a library argument, possibly subject to restrictions.
-  void emitArg(int depth, String p) {
+  void emitArg(int depth, String p, {RhsFilter rhsFilter}) {
     switch (p) {
       case 'B':
         emitExpr(depth, DartType.BOOL);
@@ -1289,19 +1395,19 @@
         emitExpr(depth, fp ? DartType.DOUBLE : DartType.INT);
         break;
       case 'S':
-        emitExpr(depth, DartType.STRING);
+        emitExpr(depth, DartType.STRING, rhsFilter: rhsFilter);
         break;
       case 's': // emit small string
         emitString(length: 2);
         break;
       case 'L':
-        emitExpr(depth, DartType.INT_LIST);
+        emitExpr(depth, DartType.INT_LIST, rhsFilter: rhsFilter);
         break;
       case 'X':
-        emitExpr(depth, DartType.INT_SET);
+        emitExpr(depth, DartType.INT_SET, rhsFilter: rhsFilter);
         break;
       case 'M':
-        emitExpr(depth, DartType.INT_STRING_MAP);
+        emitExpr(depth, DartType.INT_STRING_MAP, rhsFilter: rhsFilter);
         break;
       default:
         throw ArgumentError('Invalid p value: $p');
@@ -1332,9 +1438,9 @@
     }
   }
 
-  List<DartType> fillTypes1({bool isFfi = false}) {
+  List<DartType> fillTypes1({int limit = 4, bool isFfi = false}) {
     final list = <DartType>[];
-    for (int i = 0, n = 1 + rand.nextInt(4); i < n; i++) {
+    for (int i = 0, n = 1 + rand.nextInt(limit); i < n; i++) {
       if (isFfi) {
         list.add(fp ? oneOf([DartType.INT, DartType.DOUBLE]) : DartType.INT);
       } else {
@@ -1344,18 +1450,20 @@
     return list;
   }
 
-  List<List<DartType>> fillTypes2({bool isFfi = false, int limit = 4}) {
+  List<List<DartType>> fillTypes2(
+      {bool isFfi = false, int limit2 = 4, int limit1 = 4}) {
     final list = <List<DartType>>[];
-    for (int i = 0, n = 1 + rand.nextInt(limit); i < n; i++) {
-      list.add(fillTypes1(isFfi: isFfi));
+    for (int i = 0, n = 1 + rand.nextInt(limit2); i < n; i++) {
+      list.add(fillTypes1(limit: limit1, isFfi: isFfi));
     }
     return list;
   }
 
-  List<List<List<DartType>>> fillTypes3(int n) {
+  List<List<List<DartType>>> fillTypes3(int n,
+      {int limit2 = 4, int limit1 = 4}) {
     final list = <List<List<DartType>>>[];
     for (int i = 0; i < n; i++) {
-      list.add(fillTypes2());
+      list.add(fillTypes2(limit2: limit2, limit1: limit1));
     }
     return list;
   }
@@ -1453,7 +1561,7 @@
   // Types of global variables.
   List<DartType> globalVars;
 
-  // Names of currenty active iterator variables.
+  // Names of currently active iterator variables.
   // These are tracked to avoid modifications within the loop body,
   // which can lead to infinite loops.
   List<String> iterVars;
@@ -1467,6 +1575,10 @@
   // Prototypes of all methods over all classes (first element is return type).
   List<List<List<DartType>>> classMethods;
 
+  // List of virtual functions per class. Map is from parent class index to List
+  // of overloaded functions from that parent.
+  List<Map<int, List<int>>> virtualClassMethods;
+
   // Parent class indices for all classes.
   List<int> classParents;
 }
diff --git a/runtime/tools/dartfuzz/dartfuzz_test.dart b/runtime/tools/dartfuzz/dartfuzz_test.dart
index 3dc78e3..c1fcbe7 100644
--- a/runtime/tools/dartfuzz/dartfuzz_test.dart
+++ b/runtime/tools/dartfuzz/dartfuzz_test.dart
@@ -138,14 +138,10 @@
     if (mode.endsWith('debug-x64')) return 'DebugX64';
     if (mode.endsWith('debug-arm32')) return 'DebugSIMARM';
     if (mode.endsWith('debug-arm64')) return 'DebugSIMARM64';
-    if (mode.endsWith('debug-dbc32')) return 'DebugSIMDBC';
-    if (mode.endsWith('debug-dbc64')) return 'DebugSIMDBC64';
     if (mode.endsWith('ia32')) return 'ReleaseIA32';
     if (mode.endsWith('x64')) return 'ReleaseX64';
     if (mode.endsWith('arm32')) return 'ReleaseSIMARM';
     if (mode.endsWith('arm64')) return 'ReleaseSIMARM64';
-    if (mode.endsWith('dbc32')) return 'ReleaseSIMDBC';
-    if (mode.endsWith('dbc64')) return 'ReleaseSIMDBC64';
     throw ('unknown tag in mode: $mode');
   }
 
@@ -315,6 +311,14 @@
     print('\n${isolate}: done');
     showStatistics();
     print('');
+    if (timeoutSeeds.isNotEmpty) {
+      print('\n${isolate} timeout: ' + timeoutSeeds.join(", "));
+      print('');
+    }
+    if (skippedSeeds.isNotEmpty) {
+      print('\n${isolate} skipped: ' + skippedSeeds.join(", "));
+      print('');
+    }
 
     cleanup();
     return numDivergences;
@@ -348,6 +352,8 @@
     numRerun = 0;
     numTimeout = 0;
     numDivergences = 0;
+    timeoutSeeds = {};
+    skippedSeeds = {};
   }
 
   bool samePrecision(String mode1, String mode2) =>
@@ -427,10 +433,12 @@
         case -sigkill:
           // Both had a time out.
           numTimeout++;
+          timeoutSeeds.add(seed);
           break;
         default:
           // Both had an error.
           numSkipped++;
+          skippedSeeds.add(seed);
           break;
       }
     } else {
@@ -440,6 +448,7 @@
         // with at least one time out is treated as a regular time out.
         if (result1.exitCode == -sigkill || result2.exitCode == -sigkill) {
           numTimeout++;
+          timeoutSeeds.add(seed);
           return ReportStatus.ignored;
         }
       }
@@ -531,6 +540,8 @@
   int numRerun;
   int numTimeout;
   int numDivergences;
+  Set<int> timeoutSeeds;
+  Set<int> skippedSeeds;
 }
 
 /// Class to start fuzz testing session.
@@ -686,11 +697,6 @@
 
   // Modes not used on cluster runs because they have outstanding issues.
   static const List<String> nonClusterModes = [
-    // Deprecated.
-    'jit-debug-dbc32',
-    'jit-debug-dbc64',
-    'jit-dbc32',
-    'jit-dbc64',
     // Times out often:
     'aot-debug-arm32',
     'aot-debug-arm64',
diff --git a/runtime/tools/dartfuzz/gen_api_table.dart b/runtime/tools/dartfuzz/gen_api_table.dart
index 1231006..e4a55d6 100644
--- a/runtime/tools/dartfuzz/gen_api_table.dart
+++ b/runtime/tools/dartfuzz/gen_api_table.dart
@@ -56,6 +56,7 @@
   final provider = PhysicalResourceProvider.INSTANCE;
   final collection = AnalysisContextCollectionImpl(
       includedPaths: <String>[packageRoot],
+      excludedPaths: <String>[packageRoot + "/pkg/front_end/test"],
       resourceProvider: provider,
       sdkPath: sdkPath);
   final AnalysisSession session = collection.contexts[0].currentSession;
diff --git a/runtime/tools/dartfuzz/list_dartfuzz_versions.sh b/runtime/tools/dartfuzz/list_dartfuzz_versions.sh
new file mode 100755
index 0000000..5181ca9
--- /dev/null
+++ b/runtime/tools/dartfuzz/list_dartfuzz_versions.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+#
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+for i in $(git log --oneline | grep -- '\[vm/fuzzer\]' | awk '{print $1}')
+do
+  echo $i
+  git show $i:runtime/tools/dartfuzz/dartfuzz.dart | grep 'const String version = ' | awk '{print $NF}'
+done
+
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index a526aec..5850a97 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -13,7 +13,6 @@
 import("../../sdk/lib/isolate/isolate_sources.gni")
 import("../../sdk/lib/math/math_sources.gni")
 import("../../sdk/lib/mirrors/mirrors_sources.gni")
-import("../../sdk/lib/profiler/profiler_sources.gni")
 import("../../sdk/lib/typed_data/typed_data_sources.gni")
 import("../../sdk/lib/vmservice/vmservice_sources.gni")
 import("../../sdk/lib/wasm/wasm_sources.gni")
@@ -69,7 +68,7 @@
   extra_deps = [ "//third_party/icu" ]
   if (is_fuchsia) {
     if (using_fuchsia_sdk) {
-      extra_deps += [ "$fuchsia_sdk_root/pkg/lib/sys/cpp" ]
+      extra_deps += [ "$fuchsia_sdk_root/pkg:sys_cpp" ]
     } else {
       extra_deps += [
         # TODO(US-399): Remove time_service specific code when it is no longer
@@ -102,6 +101,9 @@
       ]
     }
   }
+  if (dart_enable_wasm) {
+    defines = [ "DART_ENABLE_WASM" ]
+  }
   include_dirs = [ ".." ]
   allsources = async_runtime_cc_files + collection_runtime_cc_files +
                core_runtime_cc_files + developer_runtime_cc_files +
diff --git a/runtime/vm/bootstrap_natives.cc b/runtime/vm/bootstrap_natives.cc
index f733331..f8030dc 100644
--- a/runtime/vm/bootstrap_natives.cc
+++ b/runtime/vm/bootstrap_natives.cc
@@ -127,11 +127,6 @@
   library.set_native_entry_symbol_resolver(symbol_resolver);
 #endif
 
-  library = Library::ProfilerLibrary();
-  ASSERT(!library.IsNull());
-  library.set_native_entry_resolver(resolver);
-  library.set_native_entry_symbol_resolver(symbol_resolver);
-
   library = Library::TypedDataLibrary();
   ASSERT(!library.IsNull());
   library.set_native_entry_resolver(resolver);
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index efccf88..c947c02 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -391,6 +391,14 @@
   V(Ffi_dl_executableLibrary, 0)                                               \
   V(TransferableTypedData_factory, 2)                                          \
   V(TransferableTypedData_materialize, 1)                                      \
+  V(Wasm_initModule, 2)                                                        \
+  V(Wasm_initImports, 2)                                                       \
+  V(Wasm_addMemoryImport, 3)                                                   \
+  V(Wasm_addGlobalImport, 5)                                                   \
+  V(Wasm_initMemory, 3)                                                        \
+  V(Wasm_growMemory, 2)                                                        \
+  V(Wasm_initInstance, 3)                                                      \
+  V(Wasm_initFunction, 4)                                                      \
   V(Wasm_callFunction, 2)
 
 // List of bootstrap native entry points used in the dart:mirror library.
diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h
index 7c129c1..69d6487 100644
--- a/runtime/vm/class_id.h
+++ b/runtime/vm/class_id.h
@@ -131,6 +131,13 @@
   V(DynamicLibrary)                                                            \
   V(Struct)
 
+#define CLASS_LIST_WASM(V)                                                     \
+  V(WasmInt32)                                                                 \
+  V(WasmInt64)                                                                 \
+  V(WasmFloat)                                                                 \
+  V(WasmDouble)                                                                \
+  V(WasmVoid)
+
 #define DART_CLASS_LIST_TYPED_DATA(V)                                          \
   V(Int8)                                                                      \
   V(Uint8)                                                                     \
@@ -182,6 +189,10 @@
   CLASS_LIST_FFI(DEFINE_OBJECT_KIND)
 #undef DEFINE_OBJECT_KIND
 
+#define DEFINE_OBJECT_KIND(clazz) k##clazz##Cid,
+  CLASS_LIST_WASM(DEFINE_OBJECT_KIND)
+#undef DEFINE_OBJECT_KIND
+
 #define DEFINE_OBJECT_KIND(clazz)                                              \
   kTypedData##clazz##Cid,                                                      \
   kTypedData##clazz##ViewCid,                                                  \
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index a5958d6..70459fd 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -300,7 +300,7 @@
     objects_.Add(type_args);
 
     s->Push(type_args->ptr()->instantiations_);
-    intptr_t length = Smi::Value(type_args->ptr()->length_);
+    const intptr_t length = Smi::Value(type_args->ptr()->length_);
     for (intptr_t i = 0; i < length; i++) {
       s->Push(type_args->ptr()->types()[i]);
     }
@@ -308,23 +308,23 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kTypeArgumentsCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawTypeArguments* type_args = objects_[i];
       s->AssignRef(type_args);
       AutoTraceObject(type_args);
-      intptr_t length = Smi::Value(type_args->ptr()->length_);
+      const intptr_t length = Smi::Value(type_args->ptr()->length_);
       s->WriteUnsigned(length);
     }
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawTypeArguments* type_args = objects_[i];
       AutoTraceObject(type_args);
-      intptr_t length = Smi::Value(type_args->ptr()->length_);
+      const intptr_t length = Smi::Value(type_args->ptr()->length_);
       s->WriteUnsigned(length);
       s->Write<bool>(type_args->IsCanonical());
       intptr_t hash = Smi::Value(type_args->ptr()->hash_);
@@ -349,9 +349,9 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
-      intptr_t length = d->ReadUnsigned();
+      const intptr_t length = d->ReadUnsigned();
       d->AssignRef(AllocateUninitialized(old_space,
                                          TypeArguments::InstanceSize(length)));
     }
@@ -362,7 +362,7 @@
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawTypeArguments* type_args =
           reinterpret_cast<RawTypeArguments*>(d->Ref(id));
-      intptr_t length = d->ReadUnsigned();
+      const intptr_t length = d->ReadUnsigned();
       bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(type_args, kTypeArgumentsCid,
                                      TypeArguments::InstanceSize(length),
@@ -393,7 +393,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kPatchClassCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawPatchClass* cls = objects_[i];
@@ -402,7 +402,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawPatchClass* cls = objects_[i];
       AutoTraceObject(cls);
@@ -426,7 +426,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, PatchClass::InstanceSize()));
@@ -475,7 +475,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kFunctionCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawFunction* func = objects_[i];
@@ -485,7 +485,7 @@
 
   void WriteFill(Serializer* s) {
     Snapshot::Kind kind = s->kind();
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawFunction* func = objects_[i];
       AutoTraceObjectName(func, func->ptr()->name_);
@@ -501,13 +501,12 @@
         WriteField(func, ic_data_array_);
       }
 
-#if !defined(DART_PRECOMPILED_RUNTIME)
       if (kind != Snapshot::kFullAOT) {
         s->WriteTokenPosition(func->ptr()->token_pos_);
         s->WriteTokenPosition(func->ptr()->end_token_pos_);
         s->Write<uint32_t>(func->ptr()->binary_declaration_);
       }
-#endif
+
       s->Write<uint32_t>(func->ptr()->packed_fields_);
       s->Write<uint32_t>(func->ptr()->kind_tag_);
     }
@@ -526,7 +525,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Function::InstanceSize()));
     }
@@ -649,7 +648,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kClosureDataCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawClosureData* data = objects_[i];
@@ -658,7 +657,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawClosureData* data = objects_[i];
       AutoTraceObject(data);
@@ -684,7 +683,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, ClosureData::InstanceSize()));
@@ -724,7 +723,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kSignatureDataCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawSignatureData* data = objects_[i];
@@ -733,7 +732,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawSignatureData* data = objects_[i];
       AutoTraceObject(data);
@@ -754,7 +753,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, SignatureData::InstanceSize()));
@@ -795,7 +794,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawFfiTrampolineData* const data = objects_[i];
       AutoTraceObject(data);
@@ -823,7 +822,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, FfiTrampolineData::InstanceSize()));
@@ -859,7 +858,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kRedirectionDataCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawRedirectionData* data = objects_[i];
@@ -868,7 +867,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawRedirectionData* data = objects_[i];
       AutoTraceObject(data);
@@ -889,7 +888,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, RedirectionData::InstanceSize()));
@@ -956,7 +955,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kFieldCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawField* field = objects_[i];
@@ -966,7 +965,7 @@
 
   void WriteFill(Serializer* s) {
     Snapshot::Kind kind = s->kind();
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawField* field = objects_[i];
       AutoTraceObjectName(field, field->ptr()->name_);
@@ -1030,7 +1029,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Field::InstanceSize()));
     }
@@ -1094,7 +1093,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kScriptCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawScript* script = objects_[i];
@@ -1103,14 +1102,14 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawScript* script = objects_[i];
       AutoTraceObjectName(script, script->ptr()->url_);
       WriteFromTo(script);
       s->Write<int32_t>(script->ptr()->line_offset_);
       s->Write<int32_t>(script->ptr()->col_offset_);
-      s->Write<int8_t>(script->ptr()->kind_);
+      s->Write<uint8_t>(script->ptr()->kind_and_tags_);
       s->Write<int32_t>(script->ptr()->kernel_script_index_);
     }
   }
@@ -1128,7 +1127,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Script::InstanceSize()));
     }
@@ -1143,7 +1142,7 @@
       ReadFromTo(script);
       script->ptr()->line_offset_ = d->Read<int32_t>();
       script->ptr()->col_offset_ = d->Read<int32_t>();
-      script->ptr()->kind_ = d->Read<int8_t>();
+      script->ptr()->kind_and_tags_ = d->Read<uint8_t>();
       script->ptr()->kernel_script_index_ = d->Read<int32_t>();
       script->ptr()->load_timestamp_ = 0;
     }
@@ -1164,7 +1163,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kLibraryCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawLibrary* lib = objects_[i];
@@ -1173,7 +1172,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawLibrary* lib = objects_[i];
       AutoTraceObjectName(lib, lib->ptr()->url_);
@@ -1202,7 +1201,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Library::InstanceSize()));
     }
@@ -1245,7 +1244,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kNamespaceCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawNamespace* ns = objects_[i];
@@ -1254,7 +1253,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawNamespace* ns = objects_[i];
       AutoTraceObject(ns);
@@ -1275,7 +1274,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Namespace::InstanceSize()));
     }
@@ -1308,7 +1307,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kKernelProgramInfoCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawKernelProgramInfo* info = objects_[i];
@@ -1317,7 +1316,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawKernelProgramInfo* info = objects_[i];
       AutoTraceObject(info);
@@ -1340,7 +1339,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, KernelProgramInfo::InstanceSize()));
@@ -1404,7 +1403,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kCodeCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawCode* code = objects_[i];
@@ -1414,7 +1413,7 @@
 
   void WriteFill(Serializer* s) {
     Snapshot::Kind kind = s->kind();
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawCode* code = objects_[i];
       AutoTraceObject(code);
@@ -1610,7 +1609,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kBytecodeCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawBytecode* bytecode = objects_[i];
@@ -1620,7 +1619,7 @@
 
   void WriteFill(Serializer* s) {
     ASSERT(s->kind() != Snapshot::kFullAOT);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawBytecode* bytecode = objects_[i];
       s->Write<int32_t>(bytecode->ptr()->instructions_size_);
@@ -1643,7 +1642,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Bytecode::InstanceSize()));
     }
@@ -1688,7 +1687,7 @@
     RawObjectPool* pool = ObjectPool::RawCast(object);
     objects_.Add(pool);
 
-    intptr_t length = pool->ptr()->length_;
+    const intptr_t length = pool->ptr()->length_;
     uint8_t* entry_bits = pool->ptr()->entry_bits();
     for (intptr_t i = 0; i < length; i++) {
       auto entry_type = ObjectPool::TypeBits::decode(entry_bits[i]);
@@ -1701,23 +1700,23 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kObjectPoolCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawObjectPool* pool = objects_[i];
       s->AssignRef(pool);
       AutoTraceObject(pool);
-      intptr_t length = pool->ptr()->length_;
+      const intptr_t length = pool->ptr()->length_;
       s->WriteUnsigned(length);
     }
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawObjectPool* pool = objects_[i];
       AutoTraceObject(pool);
-      intptr_t length = pool->ptr()->length_;
+      const intptr_t length = pool->ptr()->length_;
       s->WriteUnsigned(length);
       uint8_t* entry_bits = pool->ptr()->entry_bits();
       for (intptr_t j = 0; j < length; j++) {
@@ -1783,9 +1782,9 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
-      intptr_t length = d->ReadUnsigned();
+      const intptr_t length = d->ReadUnsigned();
       d->AssignRef(
           AllocateUninitialized(old_space, ObjectPool::InstanceSize(length)));
     }
@@ -1794,7 +1793,7 @@
 
   void ReadFill(Deserializer* d) {
     for (intptr_t id = start_index_; id < stop_index_; id += 1) {
-      intptr_t length = d->ReadUnsigned();
+      const intptr_t length = d->ReadUnsigned();
       RawObjectPool* pool = reinterpret_cast<RawObjectPool*>(d->Ref(id + 0));
       Deserializer::InitializeHeader(pool, kObjectPoolCid,
                                      ObjectPool::InstanceSize(length));
@@ -1834,6 +1833,77 @@
 };
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
+class PcDescriptorsSerializationCluster : public SerializationCluster {
+ public:
+  PcDescriptorsSerializationCluster() : SerializationCluster("PcDescriptors") {}
+  ~PcDescriptorsSerializationCluster() {}
+
+  void Trace(Serializer* s, RawObject* object) {
+    RawPcDescriptors* desc = PcDescriptors::RawCast(object);
+    objects_.Add(desc);
+  }
+
+  void WriteAlloc(Serializer* s) {
+    s->WriteCid(kPcDescriptorsCid);
+    const intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      RawPcDescriptors* desc = objects_[i];
+      s->AssignRef(desc);
+      AutoTraceObject(desc);
+      const intptr_t length = desc->ptr()->length_;
+      s->WriteUnsigned(length);
+    }
+  }
+
+  void WriteFill(Serializer* s) {
+    const intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      RawPcDescriptors* desc = objects_[i];
+      AutoTraceObject(desc);
+      const intptr_t length = desc->ptr()->length_;
+      s->WriteUnsigned(length);
+      uint8_t* cdata = reinterpret_cast<uint8_t*>(desc->ptr()->data());
+      s->WriteBytes(cdata, length);
+    }
+  }
+
+ private:
+  GrowableArray<RawPcDescriptors*> objects_;
+};
+#endif  // !DART_PRECOMPILED_RUNTIME
+
+class PcDescriptorsDeserializationCluster : public DeserializationCluster {
+ public:
+  PcDescriptorsDeserializationCluster() {}
+  ~PcDescriptorsDeserializationCluster() {}
+
+  void ReadAlloc(Deserializer* d) {
+    start_index_ = d->next_index();
+    PageSpace* old_space = d->heap()->old_space();
+    const intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      const intptr_t length = d->ReadUnsigned();
+      d->AssignRef(AllocateUninitialized(old_space,
+                                         PcDescriptors::InstanceSize(length)));
+    }
+    stop_index_ = d->next_index();
+  }
+
+  void ReadFill(Deserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id += 1) {
+      const intptr_t length = d->ReadUnsigned();
+      RawPcDescriptors* desc = reinterpret_cast<RawPcDescriptors*>(d->Ref(id));
+      Deserializer::InitializeHeader(desc, kPcDescriptorsCid,
+                                     PcDescriptors::InstanceSize(length));
+      desc->ptr()->length_ = length;
+      uint8_t* cdata = reinterpret_cast<uint8_t*>(desc->ptr()->data());
+      d->ReadBytes(cdata, length);
+    }
+  }
+};
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
 // PcDescriptor, StackMap, OneByteString, TwoByteString
 class RODataSerializationCluster : public SerializationCluster {
  public:
@@ -1951,23 +2021,23 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kExceptionHandlersCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawExceptionHandlers* handlers = objects_[i];
       s->AssignRef(handlers);
       AutoTraceObject(handlers);
-      intptr_t length = handlers->ptr()->num_entries_;
+      const intptr_t length = handlers->ptr()->num_entries_;
       s->WriteUnsigned(length);
     }
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawExceptionHandlers* handlers = objects_[i];
       AutoTraceObject(handlers);
-      intptr_t length = handlers->ptr()->num_entries_;
+      const intptr_t length = handlers->ptr()->num_entries_;
       s->WriteUnsigned(length);
       WriteField(handlers, handled_types_data_);
       for (intptr_t j = 0; j < length; j++) {
@@ -1994,9 +2064,9 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
-      intptr_t length = d->ReadUnsigned();
+      const intptr_t length = d->ReadUnsigned();
       d->AssignRef(AllocateUninitialized(
           old_space, ExceptionHandlers::InstanceSize(length)));
     }
@@ -2007,7 +2077,7 @@
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawExceptionHandlers* handlers =
           reinterpret_cast<RawExceptionHandlers*>(d->Ref(id));
-      intptr_t length = d->ReadUnsigned();
+      const intptr_t length = d->ReadUnsigned();
       Deserializer::InitializeHeader(handlers, kExceptionHandlersCid,
                                      ExceptionHandlers::InstanceSize(length));
       handlers->ptr()->num_entries_ = length;
@@ -2036,7 +2106,7 @@
     objects_.Add(context);
 
     s->Push(context->ptr()->parent_);
-    intptr_t length = context->ptr()->num_variables_;
+    const intptr_t length = context->ptr()->num_variables_;
     for (intptr_t i = 0; i < length; i++) {
       s->Push(context->ptr()->data()[i]);
     }
@@ -2044,23 +2114,23 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kContextCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawContext* context = objects_[i];
       s->AssignRef(context);
       AutoTraceObject(context);
-      intptr_t length = context->ptr()->num_variables_;
+      const intptr_t length = context->ptr()->num_variables_;
       s->WriteUnsigned(length);
     }
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawContext* context = objects_[i];
       AutoTraceObject(context);
-      intptr_t length = context->ptr()->num_variables_;
+      const intptr_t length = context->ptr()->num_variables_;
       s->WriteUnsigned(length);
       WriteField(context, parent_);
       for (intptr_t j = 0; j < length; j++) {
@@ -2082,9 +2152,9 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
-      intptr_t length = d->ReadUnsigned();
+      const intptr_t length = d->ReadUnsigned();
       d->AssignRef(
           AllocateUninitialized(old_space, Context::InstanceSize(length)));
     }
@@ -2094,7 +2164,7 @@
   void ReadFill(Deserializer* d) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawContext* context = reinterpret_cast<RawContext*>(d->Ref(id));
-      intptr_t length = d->ReadUnsigned();
+      const intptr_t length = d->ReadUnsigned();
       Deserializer::InitializeHeader(context, kContextCid,
                                      Context::InstanceSize(length));
       context->ptr()->num_variables_ = length;
@@ -2116,29 +2186,29 @@
     RawContextScope* scope = ContextScope::RawCast(object);
     objects_.Add(scope);
 
-    intptr_t length = scope->ptr()->num_variables_;
+    const intptr_t length = scope->ptr()->num_variables_;
     PushFromTo(scope, length);
   }
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kContextScopeCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawContextScope* scope = objects_[i];
       s->AssignRef(scope);
       AutoTraceObject(scope);
-      intptr_t length = scope->ptr()->num_variables_;
+      const intptr_t length = scope->ptr()->num_variables_;
       s->WriteUnsigned(length);
     }
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawContextScope* scope = objects_[i];
       AutoTraceObject(scope);
-      intptr_t length = scope->ptr()->num_variables_;
+      const intptr_t length = scope->ptr()->num_variables_;
       s->WriteUnsigned(length);
       s->Write<bool>(scope->ptr()->is_implicit_);
       WriteFromTo(scope, length);
@@ -2158,9 +2228,9 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
-      intptr_t length = d->ReadUnsigned();
+      const intptr_t length = d->ReadUnsigned();
       d->AssignRef(
           AllocateUninitialized(old_space, ContextScope::InstanceSize(length)));
     }
@@ -2170,7 +2240,7 @@
   void ReadFill(Deserializer* d) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawContextScope* scope = reinterpret_cast<RawContextScope*>(d->Ref(id));
-      intptr_t length = d->ReadUnsigned();
+      const intptr_t length = d->ReadUnsigned();
       Deserializer::InitializeHeader(scope, kContextScopeCid,
                                      ContextScope::InstanceSize(length));
       scope->ptr()->num_variables_ = length;
@@ -2195,7 +2265,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kParameterTypeCheckCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawParameterTypeCheck* check = objects_[i];
@@ -2204,7 +2274,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawParameterTypeCheck* check = objects_[i];
       s->Write<intptr_t>(check->ptr()->index_);
@@ -2225,7 +2295,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, ParameterTypeCheck::InstanceSize()));
@@ -2259,7 +2329,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kUnlinkedCallCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawUnlinkedCall* unlinked = objects_[i];
@@ -2268,7 +2338,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawUnlinkedCall* unlinked = objects_[i];
       AutoTraceObjectName(unlinked, unlinked->ptr()->target_name_);
@@ -2289,7 +2359,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, UnlinkedCall::InstanceSize()));
@@ -2322,7 +2392,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kICDataCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawICData* ic = objects_[i];
@@ -2332,7 +2402,7 @@
 
   void WriteFill(Serializer* s) {
     Snapshot::Kind kind = s->kind();
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawICData* ic = objects_[i];
       AutoTraceObjectName(ic, ic->ptr()->target_name_);
@@ -2357,7 +2427,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, ICData::InstanceSize()));
     }
@@ -2390,7 +2460,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kMegamorphicCacheCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawMegamorphicCache* cache = objects_[i];
@@ -2399,7 +2469,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawMegamorphicCache* cache = objects_[i];
       AutoTraceObjectName(cache, cache->ptr()->target_name_);
@@ -2421,7 +2491,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, MegamorphicCache::InstanceSize()));
@@ -2482,7 +2552,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kSubtypeTestCacheCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawSubtypeTestCache* cache = objects_[i];
@@ -2491,7 +2561,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawSubtypeTestCache* cache = objects_[i];
       AutoTraceObject(cache);
@@ -2512,7 +2582,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, SubtypeTestCache::InstanceSize()));
@@ -2545,7 +2615,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kLanguageErrorCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawLanguageError* error = objects_[i];
@@ -2554,7 +2624,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawLanguageError* error = objects_[i];
       AutoTraceObject(error);
@@ -2578,7 +2648,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, LanguageError::InstanceSize()));
@@ -2614,7 +2684,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kUnhandledExceptionCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawUnhandledException* exception = objects_[i];
@@ -2623,7 +2693,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawUnhandledException* exception = objects_[i];
       AutoTraceObject(exception);
@@ -2644,7 +2714,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, UnhandledException::InstanceSize()));
@@ -2692,7 +2762,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(cid_);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
 
     s->Write<int32_t>(next_field_offset_in_words_);
@@ -2706,7 +2776,7 @@
 
   void WriteFill(Serializer* s) {
     intptr_t next_field_offset = next_field_offset_in_words_ << kWordSizeLog2;
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawInstance* instance = objects_[i];
       AutoTraceObject(instance);
@@ -2737,7 +2807,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     next_field_offset_in_words_ = d->Read<int32_t>();
     instance_size_in_words_ = d->Read<int32_t>();
     intptr_t instance_size =
@@ -2795,7 +2865,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kLibraryPrefixCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawLibraryPrefix* prefix = objects_[i];
@@ -2804,7 +2874,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawLibraryPrefix* prefix = objects_[i];
       AutoTraceObject(prefix);
@@ -2827,7 +2897,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, LibraryPrefix::InstanceSize()));
@@ -3011,7 +3081,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kTypeRefCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawTypeRef* type = objects_[i];
@@ -3020,7 +3090,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawTypeRef* type = objects_[i];
       AutoTraceObject(type);
@@ -3041,7 +3111,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, TypeRef::InstanceSize()));
     }
@@ -3094,7 +3164,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kTypeParameterCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawTypeParameter* type = objects_[i];
@@ -3103,7 +3173,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawTypeParameter* type = objects_[i];
       AutoTraceObject(type);
@@ -3128,7 +3198,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, TypeParameter::InstanceSize()));
@@ -3184,7 +3254,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kClosureCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawClosure* closure = objects_[i];
@@ -3193,7 +3263,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawClosure* closure = objects_[i];
       AutoTraceObject(closure);
@@ -3215,7 +3285,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Closure::InstanceSize()));
     }
@@ -3286,7 +3356,7 @@
     PageSpace* old_space = d->heap()->old_space();
 
     start_index_ = d->next_index();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       bool is_canonical = d->Read<bool>();
       int64_t value = d->Read<int64_t>();
@@ -3333,7 +3403,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kDoubleCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawDouble* dbl = objects_[i];
@@ -3342,7 +3412,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawDouble* dbl = objects_[i];
       AutoTraceObject(dbl);
@@ -3364,7 +3434,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Double::InstanceSize()));
     }
@@ -3397,7 +3467,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kGrowableObjectArrayCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawGrowableObjectArray* array = objects_[i];
@@ -3406,7 +3476,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawGrowableObjectArray* array = objects_[i];
       AutoTraceObject(array);
@@ -3429,7 +3499,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space,
                                          GrowableObjectArray::InstanceSize()));
@@ -3464,24 +3534,24 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(cid_);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawTypedData* data = objects_[i];
       s->AssignRef(data);
       AutoTraceObject(data);
-      intptr_t length = Smi::Value(data->ptr()->length_);
+      const intptr_t length = Smi::Value(data->ptr()->length_);
       s->WriteUnsigned(length);
     }
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
     for (intptr_t i = 0; i < count; i++) {
       RawTypedData* data = objects_[i];
       AutoTraceObject(data);
-      intptr_t length = Smi::Value(data->ptr()->length_);
+      const intptr_t length = Smi::Value(data->ptr()->length_);
       s->WriteUnsigned(length);
       s->Write<bool>(data->IsCanonical());
       uint8_t* cdata = reinterpret_cast<uint8_t*>(data->ptr()->data());
@@ -3503,10 +3573,10 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
     for (intptr_t i = 0; i < count; i++) {
-      intptr_t length = d->ReadUnsigned();
+      const intptr_t length = d->ReadUnsigned();
       d->AssignRef(AllocateUninitialized(
           old_space, TypedData::InstanceSize(length * element_size)));
     }
@@ -3518,9 +3588,9 @@
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawTypedData* data = reinterpret_cast<RawTypedData*>(d->Ref(id));
-      intptr_t length = d->ReadUnsigned();
+      const intptr_t length = d->ReadUnsigned();
       bool is_canonical = d->Read<bool>();
-      intptr_t length_in_bytes = length * element_size;
+      const intptr_t length_in_bytes = length * element_size;
       Deserializer::InitializeHeader(
           data, cid_, TypedData::InstanceSize(length_in_bytes), is_canonical);
       data->ptr()->length_ = Smi::New(length);
@@ -3627,7 +3697,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(cid_);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawExternalTypedData* data = objects_[i];
@@ -3636,12 +3706,12 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_);
     for (intptr_t i = 0; i < count; i++) {
       RawExternalTypedData* data = objects_[i];
       AutoTraceObject(data);
-      intptr_t length = Smi::Value(data->ptr()->length_);
+      const intptr_t length = Smi::Value(data->ptr()->length_);
       s->WriteUnsigned(length);
       uint8_t* cdata = reinterpret_cast<uint8_t*>(data->ptr()->data_);
       s->Align(ExternalTypedData::kDataSerializationAlignment);
@@ -3663,7 +3733,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, ExternalTypedData::InstanceSize()));
@@ -3677,7 +3747,7 @@
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawExternalTypedData* data =
           reinterpret_cast<RawExternalTypedData*>(d->Ref(id));
-      intptr_t length = d->ReadUnsigned();
+      const intptr_t length = d->ReadUnsigned();
       Deserializer::InitializeHeader(data, cid_,
                                      ExternalTypedData::InstanceSize());
       data->ptr()->length_ = Smi::New(length);
@@ -3706,7 +3776,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kStackTraceCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawStackTrace* trace = objects_[i];
@@ -3715,7 +3785,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawStackTrace* trace = objects_[i];
       AutoTraceObject(trace);
@@ -3736,7 +3806,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, StackTrace::InstanceSize()));
@@ -3768,7 +3838,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kRegExpCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawRegExp* regexp = objects_[i];
@@ -3777,7 +3847,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawRegExp* regexp = objects_[i];
       AutoTraceObject(regexp);
@@ -3801,7 +3871,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, RegExp::InstanceSize()));
     }
@@ -3835,7 +3905,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kWeakPropertyCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawWeakProperty* property = objects_[i];
@@ -3844,7 +3914,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawWeakProperty* property = objects_[i];
       AutoTraceObject(property);
@@ -3865,7 +3935,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, WeakProperty::InstanceSize()));
@@ -3911,7 +3981,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kLinkedHashMapCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawLinkedHashMap* map = objects_[i];
@@ -3920,7 +3990,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawLinkedHashMap* map = objects_[i];
       AutoTraceObject(map);
@@ -3961,7 +4031,7 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, LinkedHashMap::InstanceSize()));
@@ -4021,7 +4091,7 @@
     objects_.Add(array);
 
     s->Push(array->ptr()->type_arguments_);
-    intptr_t length = Smi::Value(array->ptr()->length_);
+    const intptr_t length = Smi::Value(array->ptr()->length_);
     for (intptr_t i = 0; i < length; i++) {
       s->Push(array->ptr()->data()[i]);
     }
@@ -4029,23 +4099,23 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(cid_);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawArray* array = objects_[i];
       s->AssignRef(array);
       AutoTraceObject(array);
-      intptr_t length = Smi::Value(array->ptr()->length_);
+      const intptr_t length = Smi::Value(array->ptr()->length_);
       s->WriteUnsigned(length);
     }
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawArray* array = objects_[i];
       AutoTraceObject(array);
-      intptr_t length = Smi::Value(array->ptr()->length_);
+      const intptr_t length = Smi::Value(array->ptr()->length_);
       s->WriteUnsigned(length);
       s->Write<bool>(array->IsCanonical());
       WriteField(array, type_arguments_);
@@ -4069,9 +4139,9 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
-      intptr_t length = d->ReadUnsigned();
+      const intptr_t length = d->ReadUnsigned();
       d->AssignRef(
           AllocateUninitialized(old_space, Array::InstanceSize(length)));
     }
@@ -4081,7 +4151,7 @@
   void ReadFill(Deserializer* d) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawArray* array = reinterpret_cast<RawArray*>(d->Ref(id));
-      intptr_t length = d->ReadUnsigned();
+      const intptr_t length = d->ReadUnsigned();
       bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(array, cid_, Array::InstanceSize(length),
                                      is_canonical);
@@ -4111,23 +4181,23 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kOneByteStringCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawOneByteString* str = objects_[i];
       s->AssignRef(str);
       AutoTraceObject(str);
-      intptr_t length = Smi::Value(str->ptr()->length_);
+      const intptr_t length = Smi::Value(str->ptr()->length_);
       s->WriteUnsigned(length);
     }
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawOneByteString* str = objects_[i];
       AutoTraceObject(str);
-      intptr_t length = Smi::Value(str->ptr()->length_);
+      const intptr_t length = Smi::Value(str->ptr()->length_);
       s->WriteUnsigned(length);
       s->Write<bool>(str->IsCanonical());
       intptr_t hash = String::GetCachedHash(str);
@@ -4149,9 +4219,9 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
-      intptr_t length = d->ReadUnsigned();
+      const intptr_t length = d->ReadUnsigned();
       d->AssignRef(AllocateUninitialized(old_space,
                                          OneByteString::InstanceSize(length)));
     }
@@ -4161,7 +4231,7 @@
   void ReadFill(Deserializer* d) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawOneByteString* str = reinterpret_cast<RawOneByteString*>(d->Ref(id));
-      intptr_t length = d->ReadUnsigned();
+      const intptr_t length = d->ReadUnsigned();
       bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(str, kOneByteStringCid,
                                      OneByteString::InstanceSize(length),
@@ -4188,23 +4258,23 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kTwoByteStringCid);
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       RawTwoByteString* str = objects_[i];
       s->AssignRef(str);
       AutoTraceObject(str);
-      intptr_t length = Smi::Value(str->ptr()->length_);
+      const intptr_t length = Smi::Value(str->ptr()->length_);
       s->WriteUnsigned(length);
     }
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = objects_.length();
+    const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawTwoByteString* str = objects_[i];
       AutoTraceObject(str);
-      intptr_t length = Smi::Value(str->ptr()->length_);
+      const intptr_t length = Smi::Value(str->ptr()->length_);
       s->WriteUnsigned(length);
       s->Write<bool>(str->IsCanonical());
       intptr_t hash = String::GetCachedHash(str);
@@ -4226,9 +4296,9 @@
   void ReadAlloc(Deserializer* d) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
-      intptr_t length = d->ReadUnsigned();
+      const intptr_t length = d->ReadUnsigned();
       d->AssignRef(AllocateUninitialized(old_space,
                                          TwoByteString::InstanceSize(length)));
     }
@@ -4238,7 +4308,7 @@
   void ReadFill(Deserializer* d) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RawTwoByteString* str = reinterpret_cast<RawTwoByteString*>(d->Ref(id));
-      intptr_t length = d->ReadUnsigned();
+      const intptr_t length = d->ReadUnsigned();
       bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(str, kTwoByteStringCid,
                                      TwoByteString::InstanceSize(length),
@@ -4413,12 +4483,12 @@
       return new (Z) KernelProgramInfoSerializationCluster();
     case kCodeCid:
       return new (Z) CodeSerializationCluster();
-#if !defined(DART_PRECOMPILED_RUNTIME)
     case kBytecodeCid:
       return new (Z) BytecodeSerializationCluster();
-#endif  // !DART_PRECOMPILED_RUNTIME
     case kObjectPoolCid:
       return new (Z) ObjectPoolSerializationCluster();
+    case kPcDescriptorsCid:
+      return new (Z) PcDescriptorsSerializationCluster();
     case kExceptionHandlersCid:
       return new (Z) ExceptionHandlersSerializationCluster();
     case kContextCid:
@@ -4998,6 +5068,17 @@
     return new (Z) TypedDataDeserializationCluster(cid);
   }
 
+  if (Snapshot::IncludesCode(kind_)) {
+    switch (cid) {
+      case kPcDescriptorsCid:
+      case kCodeSourceMapCid:
+      case kStackMapCid:
+      case kOneByteStringCid:
+      case kTwoByteStringCid:
+        return new (Z) RODataDeserializationCluster();
+    }
+  }
+
   switch (cid) {
     case kClassCid:
       return new (Z) ClassDeserializationCluster();
@@ -5036,9 +5117,7 @@
     case kObjectPoolCid:
       return new (Z) ObjectPoolDeserializationCluster();
     case kPcDescriptorsCid:
-    case kCodeSourceMapCid:
-    case kStackMapCid:
-      return new (Z) RODataDeserializationCluster();
+      return new (Z) PcDescriptorsDeserializationCluster();
     case kExceptionHandlersCid:
       return new (Z) ExceptionHandlersDeserializationCluster();
     case kContextCid:
@@ -5087,20 +5166,10 @@
       return new (Z) ArrayDeserializationCluster(kArrayCid);
     case kImmutableArrayCid:
       return new (Z) ArrayDeserializationCluster(kImmutableArrayCid);
-    case kOneByteStringCid: {
-      if (Snapshot::IncludesCode(kind_)) {
-        return new (Z) RODataDeserializationCluster();
-      } else {
-        return new (Z) OneByteStringDeserializationCluster();
-      }
-    }
-    case kTwoByteStringCid: {
-      if (Snapshot::IncludesCode(kind_)) {
-        return new (Z) RODataDeserializationCluster();
-      } else {
-        return new (Z) TwoByteStringDeserializationCluster();
-      }
-    }
+    case kOneByteStringCid:
+      return new (Z) OneByteStringDeserializationCluster();
+    case kTwoByteStringCid:
+      return new (Z) TwoByteStringDeserializationCluster();
     default:
       break;
   }
diff --git a/runtime/vm/code_descriptors.cc b/runtime/vm/code_descriptors.cc
index 149de08..0d4bd00 100644
--- a/runtime/vm/code_descriptors.cc
+++ b/runtime/vm/code_descriptors.cc
@@ -102,13 +102,13 @@
              (list_[i].pc_offset == ExceptionHandlers::kInvalidPcOffset));
       handlers.SetHandlerInfo(i, list_[i].outer_try_index, list_[i].pc_offset,
                               list_[i].needs_stacktrace, has_catch_all,
-                              list_[i].token_pos, list_[i].is_generated);
+                              list_[i].is_generated);
       handlers.SetHandledTypes(i, Array::empty_array());
     } else {
       const bool has_catch_all = ContainsDynamic(*list_[i].handler_types);
       handlers.SetHandlerInfo(i, list_[i].outer_try_index, list_[i].pc_offset,
                               list_[i].needs_stacktrace, has_catch_all,
-                              list_[i].token_pos, list_[i].is_generated);
+                              list_[i].is_generated);
       handlers.SetHandledTypes(i, *list_[i].handler_types);
     }
   }
diff --git a/runtime/vm/code_descriptors.h b/runtime/vm/code_descriptors.h
index 45c7435..5e2a52f 100644
--- a/runtime/vm/code_descriptors.h
+++ b/runtime/vm/code_descriptors.h
@@ -74,7 +74,6 @@
   struct HandlerDesc {
     intptr_t outer_try_index;    // Try block in which this try block is nested.
     intptr_t pc_offset;          // Handler PC offset value.
-    TokenPosition token_pos;     // Token position of handler.
     bool is_generated;           // False if this is directly from Dart code.
     const Array* handler_types;  // Catch clause guards.
     bool needs_stacktrace;
@@ -88,7 +87,6 @@
     struct HandlerDesc data;
     data.outer_try_index = -1;
     data.pc_offset = ExceptionHandlers::kInvalidPcOffset;
-    data.token_pos = TokenPosition::kNoSource;
     data.is_generated = true;
     data.handler_types = NULL;
     data.needs_stacktrace = false;
@@ -98,7 +96,6 @@
   void AddHandler(intptr_t try_index,
                   intptr_t outer_try_index,
                   intptr_t pc_offset,
-                  TokenPosition token_pos,
                   bool is_generated,
                   const Array& handler_types,
                   bool needs_stacktrace) {
@@ -109,7 +106,6 @@
     list_[try_index].outer_try_index = outer_try_index;
     ASSERT(list_[try_index].pc_offset == ExceptionHandlers::kInvalidPcOffset);
     list_[try_index].pc_offset = pc_offset;
-    list_[try_index].token_pos = token_pos;
     list_[try_index].is_generated = is_generated;
     ASSERT(handler_types.IsZoneHandle());
     list_[try_index].handler_types = &handler_types;
diff --git a/runtime/vm/code_patcher_ia32.cc b/runtime/vm/code_patcher_ia32.cc
index 81fa738..7e97f67 100644
--- a/runtime/vm/code_patcher_ia32.cc
+++ b/runtime/vm/code_patcher_ia32.cc
@@ -64,8 +64,10 @@
   }
 
   void set_native_function(NativeFunction func) const {
-    WritableInstructionsScope writable(start_ + 1, sizeof(func));
-    *reinterpret_cast<NativeFunction*>(start_ + 1) = func;
+    Thread::Current()->isolate_group()->RunWithStoppedMutators([&]() {
+      WritableInstructionsScope writable(start_ + 1, sizeof(func));
+      *reinterpret_cast<NativeFunction*>(start_ + 1) = func;
+    });
   }
 
  private:
@@ -179,11 +181,15 @@
 void CodePatcher::PatchStaticCallAt(uword return_address,
                                     const Code& code,
                                     const Code& new_target) {
-  const Instructions& instrs = Instructions::Handle(code.instructions());
-  WritableInstructionsScope writable(instrs.PayloadStart(), instrs.Size());
-  ASSERT(code.ContainsInstructionAt(return_address));
-  StaticCall call(return_address);
-  call.set_target(new_target);
+  auto thread = Thread::Current();
+  auto zone = thread->zone();
+  const Instructions& instrs = Instructions::Handle(zone, code.instructions());
+  thread->isolate_group()->RunWithStoppedMutators([&]() {
+    WritableInstructionsScope writable(instrs.PayloadStart(), instrs.Size());
+    ASSERT(code.ContainsInstructionAt(return_address));
+    StaticCall call(return_address);
+    call.set_target(new_target);
+  });
 }
 
 void CodePatcher::InsertDeoptimizationCallAt(uword start) {
@@ -205,12 +211,17 @@
                                       const Code& caller_code,
                                       const Object& data,
                                       const Code& target) {
+  auto thread = Thread::Current();
+  auto zone = thread->zone();
   ASSERT(caller_code.ContainsInstructionAt(return_address));
-  const Instructions& instrs = Instructions::Handle(caller_code.instructions());
-  WritableInstructionsScope writable(instrs.PayloadStart(), instrs.Size());
-  InstanceCall call(return_address);
-  call.set_data(data);
-  call.set_target(target);
+  const Instructions& instrs =
+      Instructions::Handle(zone, caller_code.instructions());
+  thread->isolate_group()->RunWithStoppedMutators([&]() {
+    WritableInstructionsScope writable(instrs.PayloadStart(), instrs.Size());
+    InstanceCall call(return_address);
+    call.set_data(data);
+    call.set_target(target);
+  });
 }
 
 RawFunction* CodePatcher::GetUnoptimizedStaticCallAt(uword return_address,
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 3e9c86ea..b92b714 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -4,6 +4,8 @@
 
 #include "vm/compiler/aot/precompiler.h"
 
+#ifndef DART_PRECOMPILED_RUNTIME
+
 #include "platform/unicode.h"
 #include "vm/class_finalizer.h"
 #include "vm/code_patcher.h"
@@ -2892,3 +2894,5 @@
         // !defined(TARGET_ARCH_IA32)
 
 }  // namespace dart
+
+#endif  // DART_PRECOMPILED_RUNTIME
diff --git a/runtime/vm/compiler/aot/precompiler.h b/runtime/vm/compiler/aot/precompiler.h
index a6ceb59..545f193 100644
--- a/runtime/vm/compiler/aot/precompiler.h
+++ b/runtime/vm/compiler/aot/precompiler.h
@@ -5,6 +5,8 @@
 #ifndef RUNTIME_VM_COMPILER_AOT_PRECOMPILER_H_
 #define RUNTIME_VM_COMPILER_AOT_PRECOMPILER_H_
 
+#ifndef DART_PRECOMPILED_RUNTIME
+
 #include "vm/allocation.h"
 #include "vm/compiler/assembler/assembler.h"
 #include "vm/hash_map.h"
@@ -96,13 +98,11 @@
   static Value ValueOf(Pair kv) { return kv; }
 
   static inline intptr_t Hashcode(Key key) {
-    // We are using pointer hash for objects originating from Kernel because
-    // Fasta currently does not assign any position information to them.
-    if (key->kernel_offset() > 0) {
-      return key->kernel_offset();
-    } else {
-      return key->token_pos().value();
+    const TokenPosition token_pos = key->token_pos();
+    if (token_pos.IsReal()) {
+      return token_pos.value();
     }
+    return key->binary_declaration_offset();
   }
 
   static inline bool IsKeyEqual(Pair pair, Key key) {
@@ -557,4 +557,6 @@
 
 }  // namespace dart
 
+#endif  // DART_PRECOMPILED_RUNTIME
+
 #endif  // RUNTIME_VM_COMPILER_AOT_PRECOMPILER_H_
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index 6958b22..0902183 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -546,34 +546,35 @@
 }
 
 void Assembler::EnterSafepoint(Register addr, Register state) {
+  // 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) {
-    EnterSafepointSlowly();
-  } else {
-    Label slow_path, done, retry;
-    LoadImmediate(addr, target::Thread::safepoint_state_offset());
-    add(addr, THR, Operand(addr));
-    Bind(&retry);
-    ldrex(state, addr);
-    cmp(state, Operand(target::Thread::safepoint_state_unacquired()));
-    b(&slow_path, NE);
-
-    mov(state, Operand(target::Thread::safepoint_state_acquired()));
-    strex(TMP, state, addr);
-    cmp(TMP, Operand(0));  // 0 means strex was successful.
-    b(&done, EQ);
-    b(&retry);
-
-    Bind(&slow_path);
-    EnterSafepointSlowly();
-
-    Bind(&done);
+    b(&slow_path);
   }
-}
 
-void Assembler::EnterSafepointSlowly() {
+  LoadImmediate(addr, target::Thread::safepoint_state_offset());
+  add(addr, THR, Operand(addr));
+  Bind(&retry);
+  ldrex(state, addr);
+  cmp(state, Operand(target::Thread::safepoint_state_unacquired()));
+  b(&slow_path, NE);
+
+  mov(state, Operand(target::Thread::safepoint_state_acquired()));
+  strex(TMP, state, addr);
+  cmp(TMP, Operand(0));  // 0 means strex was successful.
+  b(&done, EQ);
+
+  if (!FLAG_use_slow_path && TargetCPUFeatures::arm_version() != ARMv5TE) {
+    b(&retry);
+  }
+
+  Bind(&slow_path);
   ldr(TMP, Address(THR, target::Thread::enter_safepoint_stub_offset()));
   ldr(TMP, FieldAddress(TMP, target::Code::entry_point_offset()));
   blx(TMP);
+
+  Bind(&done);
 }
 
 void Assembler::TransitionGeneratedToNative(Register destination_address,
@@ -597,34 +598,35 @@
 }
 
 void Assembler::ExitSafepoint(Register addr, Register state) {
+  // 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) {
-    ExitSafepointSlowly();
-  } else {
-    Label slow_path, done, retry;
-    LoadImmediate(addr, target::Thread::safepoint_state_offset());
-    add(addr, THR, Operand(addr));
-    Bind(&retry);
-    ldrex(state, addr);
-    cmp(state, Operand(target::Thread::safepoint_state_acquired()));
-    b(&slow_path, NE);
-
-    mov(state, Operand(target::Thread::safepoint_state_unacquired()));
-    strex(TMP, state, addr);
-    cmp(TMP, Operand(0));  // 0 means strex was successful.
-    b(&done, EQ);
-    b(&retry);
-
-    Bind(&slow_path);
-    ExitSafepointSlowly();
-
-    Bind(&done);
+    b(&slow_path);
   }
-}
 
-void Assembler::ExitSafepointSlowly() {
+  LoadImmediate(addr, target::Thread::safepoint_state_offset());
+  add(addr, THR, Operand(addr));
+  Bind(&retry);
+  ldrex(state, addr);
+  cmp(state, Operand(target::Thread::safepoint_state_acquired()));
+  b(&slow_path, NE);
+
+  mov(state, Operand(target::Thread::safepoint_state_unacquired()));
+  strex(TMP, state, addr);
+  cmp(TMP, Operand(0));  // 0 means strex was successful.
+  b(&done, EQ);
+
+  if (!FLAG_use_slow_path && TargetCPUFeatures::arm_version() != ARMv5TE) {
+    b(&retry);
+  }
+
+  Bind(&slow_path);
   ldr(TMP, Address(THR, target::Thread::exit_safepoint_stub_offset()));
   ldr(TMP, FieldAddress(TMP, target::Code::entry_point_offset()));
   blx(TMP);
+
+  Bind(&done);
 }
 
 void Assembler::TransitionNativeToGenerated(Register addr,
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index 667f8a5..904890d 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -1337,9 +1337,6 @@
                              CanBeSmi can_be_smi,
                              BarrierFilterMode barrier_filter_mode);
 
-  void EnterSafepointSlowly();
-  void ExitSafepointSlowly();
-
   friend class dart::FlowGraphCompiler;
   std::function<void(Condition, Register)>
       generate_invoke_write_barrier_wrapper_;
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index e75fcc9..d973ac9 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -1307,21 +1307,29 @@
 }
 
 void Assembler::EnterSafepoint(Register state) {
+  // We generate the same number of instructions whether or not the slow-path is
+  // forced. This simplifies GenerateJitCallbackTrampolines.
+
   Register addr = TMP2;
   ASSERT(addr != state);
 
   Label slow_path, done, retry;
-  if (!FLAG_use_slow_path) {
-    movz(addr, Immediate(target::Thread::safepoint_state_offset()), 0);
-    add(addr, THR, Operand(addr));
-    Bind(&retry);
-    ldxr(state, addr);
-    cmp(state, Operand(target::Thread::safepoint_state_unacquired()));
-    b(&slow_path, NE);
+  if (FLAG_use_slow_path) {
+    b(&slow_path);
+  }
 
-    movz(state, Immediate(target::Thread::safepoint_state_acquired()), 0);
-    stxr(TMP, state, addr);
-    cbz(&done, TMP);  // 0 means stxr was successful.
+  movz(addr, Immediate(target::Thread::safepoint_state_offset()), 0);
+  add(addr, THR, Operand(addr));
+  Bind(&retry);
+  ldxr(state, addr);
+  cmp(state, Operand(target::Thread::safepoint_state_unacquired()));
+  b(&slow_path, NE);
+
+  movz(state, Immediate(target::Thread::safepoint_state_acquired()), 0);
+  stxr(TMP, state, addr);
+  cbz(&done, TMP);  // 0 means stxr was successful.
+
+  if (!FLAG_use_slow_path) {
     b(&retry);
   }
 
@@ -1352,21 +1360,28 @@
 }
 
 void Assembler::ExitSafepoint(Register state) {
+  // We generate the same number of instructions whether or not the slow-path is
+  // forced, for consistency with EnterSafepoint.
   Register addr = TMP2;
   ASSERT(addr != state);
 
   Label slow_path, done, retry;
-  if (!FLAG_use_slow_path) {
-    movz(addr, Immediate(target::Thread::safepoint_state_offset()), 0);
-    add(addr, THR, Operand(addr));
-    Bind(&retry);
-    ldxr(state, addr);
-    cmp(state, Operand(target::Thread::safepoint_state_acquired()));
-    b(&slow_path, NE);
+  if (FLAG_use_slow_path) {
+    b(&slow_path);
+  }
 
-    movz(state, Immediate(target::Thread::safepoint_state_unacquired()), 0);
-    stxr(TMP, state, addr);
-    cbz(&done, TMP);  // 0 means stxr was successful.
+  movz(addr, Immediate(target::Thread::safepoint_state_offset()), 0);
+  add(addr, THR, Operand(addr));
+  Bind(&retry);
+  ldxr(state, addr);
+  cmp(state, Operand(target::Thread::safepoint_state_acquired()));
+  b(&slow_path, NE);
+
+  movz(state, Immediate(target::Thread::safepoint_state_unacquired()), 0);
+  stxr(TMP, state, addr);
+  cbz(&done, TMP);  // 0 means stxr was successful.
+
+  if (!FLAG_use_slow_path) {
     b(&retry);
   }
 
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index 315e72f..972b1dc 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -1542,8 +1542,8 @@
 
   // Emit code to transition between generated mode and native mode.
   //
-  // These require that CSP and SP are equal and aligned and require a scratch
-  // register (in addition to TMP/TMP2).
+  // These require and ensure that CSP and SP are equal and aligned and require
+  // a scratch register (in addition to TMP/TMP2).
 
   void TransitionGeneratedToNative(Register destination_address,
                                    Register new_exit_frame,
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index 4943f780..63cab25 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -1499,6 +1499,13 @@
   EmitUint8(0xD0 | reg);
 }
 
+void Assembler::bsfl(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0xBC);
+  EmitRegisterOperand(dst, src);
+}
+
 void Assembler::bsrl(Register dst, Register src) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x0F);
@@ -1506,6 +1513,24 @@
   EmitRegisterOperand(dst, src);
 }
 
+void Assembler::popcntl(Register dst, Register src) {
+  ASSERT(TargetCPUFeatures::popcnt_supported());
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0x0F);
+  EmitUint8(0xB8);
+  EmitRegisterOperand(dst, src);
+}
+
+void Assembler::lzcntl(Register dst, Register src) {
+  ASSERT(TargetCPUFeatures::abm_supported());
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0x0F);
+  EmitUint8(0xBD);
+  EmitRegisterOperand(dst, src);
+}
+
 void Assembler::bt(Register base, Register offset) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x0F);
@@ -2142,21 +2167,29 @@
 }
 
 void Assembler::EnterSafepoint(Register scratch) {
+  // We generate the same number of instructions whether or not the slow-path is
+  // forced. This simplifies GenerateJitCallbackTrampolines.
+
   // Compare and swap the value at Thread::safepoint_state from unacquired to
   // acquired. On success, jump to 'success'; otherwise, fallthrough.
-  Label done;
+  Label done, slow_path;
+  if (FLAG_use_slow_path) {
+    jmp(&slow_path);
+  }
+
+  pushl(EAX);
+  movl(EAX, Immediate(target::Thread::safepoint_state_unacquired()));
+  movl(scratch, Immediate(target::Thread::safepoint_state_acquired()));
+  LockCmpxchgl(Address(THR, target::Thread::safepoint_state_offset()), scratch);
+  movl(scratch, EAX);
+  popl(EAX);
+  cmpl(scratch, Immediate(target::Thread::safepoint_state_unacquired()));
+
   if (!FLAG_use_slow_path) {
-    pushl(EAX);
-    movl(EAX, Immediate(target::Thread::safepoint_state_unacquired()));
-    movl(scratch, Immediate(target::Thread::safepoint_state_acquired()));
-    LockCmpxchgl(Address(THR, target::Thread::safepoint_state_offset()),
-                 scratch);
-    movl(scratch, EAX);
-    popl(EAX);
-    cmpl(scratch, Immediate(target::Thread::safepoint_state_unacquired()));
     j(EQUAL, &done);
   }
 
+  Bind(&slow_path);
   movl(scratch, Address(THR, target::Thread::enter_safepoint_stub_offset()));
   movl(scratch, FieldAddress(scratch, target::Code::entry_point_offset()));
   call(scratch);
@@ -2183,21 +2216,29 @@
 }
 
 void Assembler::ExitSafepoint(Register scratch) {
+  // We generate the same number of instructions whether or not the slow-path is
+  // forced, for consistency with EnterSafepoint.
+
   // Compare and swap the value at Thread::safepoint_state from acquired to
   // unacquired. On success, jump to 'success'; otherwise, fallthrough.
-  Label done;
+  Label done, slow_path;
+  if (FLAG_use_slow_path) {
+    jmp(&slow_path);
+  }
+
+  pushl(EAX);
+  movl(EAX, Immediate(target::Thread::safepoint_state_acquired()));
+  movl(scratch, Immediate(target::Thread::safepoint_state_unacquired()));
+  LockCmpxchgl(Address(THR, target::Thread::safepoint_state_offset()), scratch);
+  movl(scratch, EAX);
+  popl(EAX);
+  cmpl(scratch, Immediate(target::Thread::safepoint_state_acquired()));
+
   if (!FLAG_use_slow_path) {
-    pushl(EAX);
-    movl(EAX, Immediate(target::Thread::safepoint_state_acquired()));
-    movl(scratch, Immediate(target::Thread::safepoint_state_unacquired()));
-    LockCmpxchgl(Address(THR, target::Thread::safepoint_state_offset()),
-                 scratch);
-    movl(scratch, EAX);
-    popl(EAX);
-    cmpl(scratch, Immediate(target::Thread::safepoint_state_acquired()));
     j(EQUAL, &done);
   }
 
+  Bind(&slow_path);
   movl(scratch, Address(THR, target::Thread::exit_safepoint_stub_offset()));
   movl(scratch, FieldAddress(scratch, target::Code::entry_point_offset()));
   call(scratch);
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h
index 8321841..e4e86c1 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.h
+++ b/runtime/vm/compiler/assembler/assembler_ia32.h
@@ -527,7 +527,10 @@
   void negl(Register reg);
   void notl(Register reg);
 
+  void bsfl(Register dst, Register src);
   void bsrl(Register dst, Register src);
+  void popcntl(Register dst, Register src);
+  void lzcntl(Register dst, Register src);
 
   void bt(Register base, Register offset);
   void bt(Register base, int bit);
diff --git a/runtime/vm/compiler/assembler/assembler_ia32_test.cc b/runtime/vm/compiler/assembler/assembler_ia32_test.cc
index ca0ab3a..3bfccc0 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32_test.cc
@@ -326,6 +326,84 @@
       "ret\n");
 }
 
+ASSEMBLER_TEST_GENERATE(Bsf, assembler) {
+  __ movl(ECX, Immediate(12));
+  __ bsfl(EAX, ECX);
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(Bsf, test) {
+  typedef int (*BsfCode)();
+  EXPECT_EQ(2, reinterpret_cast<BsfCode>(test->entry())());
+  EXPECT_DISASSEMBLY(
+      "mov ecx,0xc\n"
+      "bsf eax,ecx\n"
+      "ret\n");
+}
+
+ASSEMBLER_TEST_GENERATE(Bsr, assembler) {
+  __ movl(ECX, Immediate(12));
+  __ bsrl(EAX, ECX);
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(Bsr, test) {
+  typedef int (*BsrCode)();
+  EXPECT_EQ(3, reinterpret_cast<BsrCode>(test->entry())());
+  EXPECT_DISASSEMBLY(
+      "mov ecx,0xc\n"
+      "bsr eax,ecx\n"
+      "ret\n");
+}
+
+ASSEMBLER_TEST_GENERATE(Popcnt, assembler) {
+  __ movl(ECX, Immediate(-1));
+  __ popcntl(EAX, ECX);
+  __ movl(ECX, Immediate(0xf));
+  __ popcntl(ECX, ECX);
+  __ addl(EAX, ECX);
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(Popcnt, test) {
+  if (!HostCPUFeatures::popcnt_supported()) {
+    return;
+  }
+  typedef int (*PopcntCode)();
+  EXPECT_EQ(36, reinterpret_cast<PopcntCode>(test->entry())());
+  EXPECT_DISASSEMBLY(
+      "mov ecx,0x........\n"
+      "popcnt eax,ecx\n"
+      "mov ecx,0xf\n"
+      "popcnt ecx,ecx\n"
+      "add eax,ecx\n"
+      "ret\n");
+}
+
+ASSEMBLER_TEST_GENERATE(Lzcnt, assembler) {
+  __ movl(ECX, Immediate(0x0f00));
+  __ lzcntl(EAX, ECX);
+  __ movl(ECX, Immediate(0x00f0));
+  __ lzcntl(ECX, ECX);
+  __ addl(EAX, ECX);
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(Lzcnt, test) {
+  if (!HostCPUFeatures::abm_supported()) {
+    return;
+  }
+  typedef int (*LzcntCode)();
+  EXPECT_EQ(44, reinterpret_cast<LzcntCode>(test->entry())());
+  EXPECT_DISASSEMBLY(
+      "mov ecx,0x...\n"
+      "lzcnt eax,ecx\n"
+      "mov ecx,0xf0\n"
+      "lzcnt ecx,ecx\n"
+      "add eax,ecx\n"
+      "ret\n");
+}
+
 struct JumpAddress {
   uword filler1;
   uword filler2;
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index 9c1cb4f..c9e1299 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -161,20 +161,28 @@
 }
 
 void Assembler::EnterSafepoint() {
+  // We generate the same number of instructions whether or not the slow-path is
+  // forced, to simplify GenerateJitCallbackTrampolines.
+  Label done, slow_path;
+  if (FLAG_use_slow_path) {
+    jmp(&slow_path);
+  }
+
   // Compare and swap the value at Thread::safepoint_state from unacquired to
   // acquired. If the CAS fails, go to a slow-path stub.
-  Label done;
+  pushq(RAX);
+  movq(RAX, Immediate(target::Thread::safepoint_state_unacquired()));
+  movq(TMP, Immediate(target::Thread::safepoint_state_acquired()));
+  LockCmpxchgq(Address(THR, target::Thread::safepoint_state_offset()), TMP);
+  movq(TMP, RAX);
+  popq(RAX);
+  cmpq(TMP, Immediate(target::Thread::safepoint_state_unacquired()));
+
   if (!FLAG_use_slow_path) {
-    pushq(RAX);
-    movq(RAX, Immediate(target::Thread::safepoint_state_unacquired()));
-    movq(TMP, Immediate(target::Thread::safepoint_state_acquired()));
-    LockCmpxchgq(Address(THR, target::Thread::safepoint_state_offset()), TMP);
-    movq(TMP, RAX);
-    popq(RAX);
-    cmpq(TMP, Immediate(target::Thread::safepoint_state_unacquired()));
     j(EQUAL, &done);
   }
 
+  Bind(&slow_path);
   movq(TMP, Address(THR, target::Thread::enter_safepoint_stub_offset()));
   movq(TMP, FieldAddress(TMP, target::Code::entry_point_offset()));
 
@@ -203,20 +211,29 @@
 }
 
 void Assembler::LeaveSafepoint() {
+  // We generate the same number of instructions whether or not the slow-path is
+  // forced, for consistency with EnterSafepoint.
+  Label done, slow_path;
+  if (FLAG_use_slow_path) {
+    jmp(&slow_path);
+  }
+
   // Compare and swap the value at Thread::safepoint_state from acquired to
   // unacquired. On success, jump to 'success'; otherwise, fallthrough.
-  Label done;
+
+  pushq(RAX);
+  movq(RAX, Immediate(target::Thread::safepoint_state_acquired()));
+  movq(TMP, Immediate(target::Thread::safepoint_state_unacquired()));
+  LockCmpxchgq(Address(THR, target::Thread::safepoint_state_offset()), TMP);
+  movq(TMP, RAX);
+  popq(RAX);
+  cmpq(TMP, Immediate(target::Thread::safepoint_state_acquired()));
+
   if (!FLAG_use_slow_path) {
-    pushq(RAX);
-    movq(RAX, Immediate(target::Thread::safepoint_state_acquired()));
-    movq(TMP, Immediate(target::Thread::safepoint_state_unacquired()));
-    LockCmpxchgq(Address(THR, target::Thread::safepoint_state_offset()), TMP);
-    movq(TMP, RAX);
-    popq(RAX);
-    cmpq(TMP, Immediate(target::Thread::safepoint_state_acquired()));
     j(EQUAL, &done);
   }
 
+  Bind(&slow_path);
   movq(TMP, Address(THR, target::Thread::exit_safepoint_stub_offset()));
   movq(TMP, FieldAddress(TMP, target::Code::entry_point_offset()));
 
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index 4065bdd..0c4a5e6 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -334,7 +334,10 @@
   REGULAR_INSTRUCTION(test, 0x85)
   REGULAR_INSTRUCTION(xchg, 0x87)
   REGULAR_INSTRUCTION(imul, 0xAF, 0x0F)
+  REGULAR_INSTRUCTION(bsf, 0xBC, 0x0F)
   REGULAR_INSTRUCTION(bsr, 0xBD, 0x0F)
+  REGULAR_INSTRUCTION(popcnt, 0xB8, 0x0F, 0xF3)
+  REGULAR_INSTRUCTION(lzcnt, 0xBD, 0x0F, 0xF3)
 #undef REGULAR_INSTRUCTION
   RA(Q, movsxd, 0x63)
   RR(Q, movsxd, 0x63)
diff --git a/runtime/vm/compiler/assembler/assembler_x64_test.cc b/runtime/vm/compiler/assembler/assembler_x64_test.cc
index 2e4609f..ef0619a 100644
--- a/runtime/vm/compiler/assembler/assembler_x64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64_test.cc
@@ -6,6 +6,7 @@
 #if defined(TARGET_ARCH_X64)
 
 #include "vm/compiler/assembler/assembler.h"
+#include "vm/cpu.h"
 #include "vm/os.h"
 #include "vm/unit_test.h"
 #include "vm/virtual_memory.h"
@@ -552,7 +553,7 @@
 }
 
 ASSEMBLER_TEST_GENERATE(Testb2, assembler) {
-  Label done, ok1, ok2, ok3, ok4, ok5, ok6;
+  Label done, ok1, ok2, ok3, ok4, ok5, ok6, ok7;
 
   __ movq(RAX, Immediate(0xffffefff));
   __ bsrq(RCX, RAX);
@@ -593,6 +594,13 @@
   __ int3();
   __ Bind(&ok6);
 
+  __ movq(RAX, Immediate(0x0fffeff0));
+  __ bsfq(RCX, RAX);
+  __ cmpq(RCX, Immediate(4));
+  __ j(EQUAL, &ok7);
+  __ int3();
+  __ Bind(&ok7);
+
   __ movq(RAX, Immediate(42));
   __ ret();
 }
@@ -634,6 +642,12 @@
       "jz 0x................\n"
       "int3\n"
 
+      "movl rax,0x........\n"
+      "bsfq rcx,rax\n"
+      "cmpq rcx,4\n"
+      "jz 0x................\n"
+      "int3\n"
+
       "movl rax,0x2a\n"
       "ret\n");
 }
@@ -670,6 +684,54 @@
       "ret\n");
 }
 
+ASSEMBLER_TEST_GENERATE(Popcnt, assembler) {
+  __ movq(RCX, Immediate(-1));
+  __ popcntq(RAX, RCX);
+  __ movq(RCX, Immediate(0xf));
+  __ popcntq(RCX, RCX);
+  __ addq(RAX, RCX);
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(Popcnt, test) {
+  if (!HostCPUFeatures::popcnt_supported()) {
+    return;
+  }
+  typedef int64_t (*PopcntCode)();
+  EXPECT_EQ(68, reinterpret_cast<PopcntCode>(test->entry())());
+  EXPECT_DISASSEMBLY(
+      "movq rcx,-1\n"
+      "popcntq rax,rcx\n"
+      "movl rcx,0xf\n"
+      "popcntq rcx,rcx\n"
+      "addq rax,rcx\n"
+      "ret\n");
+}
+
+ASSEMBLER_TEST_GENERATE(Lzcnt, assembler) {
+  __ movq(RCX, Immediate(0x0f00));
+  __ lzcntq(RAX, RCX);
+  __ movq(RCX, Immediate(0x00f0));
+  __ lzcntq(RCX, RCX);
+  __ addq(RAX, RCX);
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(Lzcnt, test) {
+  if (!HostCPUFeatures::abm_supported()) {
+    return;
+  }
+  typedef int64_t (*LzcntCode)();
+  EXPECT_EQ(108, reinterpret_cast<LzcntCode>(test->entry())());
+  EXPECT_DISASSEMBLY(
+      "movl rcx,0x...\n"
+      "lzcntq rax,rcx\n"
+      "movl rcx,0xf0\n"
+      "lzcntq rcx,rcx\n"
+      "addq rax,rcx\n"
+      "ret\n");
+}
+
 struct JumpAddress {
   uword filler1;
   uword filler2;
diff --git a/runtime/vm/compiler/assembler/disassembler_x86.cc b/runtime/vm/compiler/assembler/disassembler_x86.cc
index 6fd177e..b51f464 100644
--- a/runtime/vm/compiler/assembler/disassembler_x86.cc
+++ b/runtime/vm/compiler/assembler/disassembler_x86.cc
@@ -1442,6 +1442,12 @@
       get_modrm(*current, &mod, &regop, &rm);
       Print("cvtdq2pd %s,", NameOfXMMRegister(regop));
       current += PrintRightXMMOperand(current);
+    } else if (opcode == 0xB8) {
+      // POPCNT.
+      current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current);
+    } else if (opcode == 0xBD) {
+      // LZCNT (rep BSR encoding).
+      current += PrintOperands("lzcnt", REG_OPER_OP_ORDER, current);
     } else {
       UnimplementedInstruction();
     }
@@ -1585,7 +1591,7 @@
         "cpuid", "bt",   "shld",    "shld",    NULL,     NULL,
         NULL,    NULL,   NULL,      "bts",     "shrd",   "shrd",
         NULL,    "imul", "cmpxchg", "cmpxchg", NULL,     NULL,
-        NULL,    NULL,   "movzxb",  "movzxw",  NULL,     NULL,
+        NULL,    NULL,   "movzxb",  "movzxw",  "popcnt", NULL,
         NULL,    NULL,   "bsf",     "bsr",     "movsxb", "movsxw"};
     return mnemonics[opcode - 0xA2];
   }
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 27cdef7..7447b7e 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -780,7 +780,7 @@
     Instance& obj = Instance::Handle(Z, field.StaticValue());
     if (field.is_final() && (obj.raw() != Object::sentinel().raw()) &&
         (obj.raw() != Object::transition_sentinel().raw())) {
-      if (obj.IsSmi() || obj.IsOld()) {
+      if (obj.IsSmi() || (obj.IsOld() && obj.IsCanonical())) {
         SetValue(instr, obj);
         return;
       }
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index c883852..7c52d628 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -989,20 +989,10 @@
   // Add global constants to the initial definitions.
   CreateCommonConstants();
 
-  // During regular execution, only the direct parameters appear in
-  // the fixed part of the environment. During OSR, however, all
-  // variables and possibly a non-empty stack are passed as
-  // parameters. The latter mimics the incoming expression stack
-  // that was set up prior to triggering OSR.
-  const intptr_t parameter_count =
-      IsCompiledForOsr() ? osr_variable_count() : num_direct_parameters_;
-
   // Initial renaming environment.
-  GrowableArray<Definition*> env(parameter_count + num_stack_locals());
-  env.FillWith(constant_dead(), 0, parameter_count);
-  if (!IsCompiledForOsr()) {
-    env.FillWith(constant_null(), parameter_count, num_stack_locals());
-  }
+  GrowableArray<Definition*> env(variable_count());
+  env.FillWith(constant_dead(), 0, num_direct_parameters());
+  env.FillWith(constant_null(), num_direct_parameters(), num_stack_locals());
 
   if (entry->catch_entries().length() > 0) {
     // Functions with try-catch have a fixed area of stack slots reserved
@@ -1013,6 +1003,21 @@
     ASSERT(entry->unchecked_entry() != nullptr ? entry->SuccessorCount() == 2
                                                : entry->SuccessorCount() == 1);
   }
+
+  // For OSR on a non-empty stack, insert synthetic phis on the joining entry.
+  // These phis are synthetic since they are not driven by live variable
+  // analysis, but merely serve the purpose of merging stack slots from
+  // parameters and other predecessors at the block in which OSR occurred.
+  if (IsCompiledForOsr()) {
+    JoinEntryInstr* join =
+        entry->osr_entry()->last_instruction()->SuccessorAt(0)->AsJoinEntry();
+    ASSERT(join != nullptr);
+    const intptr_t parameter_count = osr_variable_count();
+    for (intptr_t i = variable_count(); i < parameter_count; i++) {
+      join->InsertPhi(i, parameter_count)->mark_alive();
+    }
+  }
+
   RenameRecursive(entry, &env, live_phis, variable_liveness,
                   inlining_parameters);
 }
@@ -1088,26 +1093,18 @@
     OsrEntryInstr* osr_entry,
     GrowableArray<Definition*>* env) {
   ASSERT(IsCompiledForOsr());
+  // During OSR, all variables and possibly a non-empty stack are
+  // passed as parameters. The latter mimics the incoming expression
+  // stack that was set up prior to triggering OSR.
   const intptr_t parameter_count = osr_variable_count();
-  // Initialize the initial enviroment.
-  ASSERT(parameter_count <= env->length());
+  ASSERT(env->length() == (parameter_count - osr_entry->stack_depth()));
+  env->EnsureLength(parameter_count, constant_dead());
   for (intptr_t i = 0; i < parameter_count; i++) {
     ParameterInstr* param = new (zone()) ParameterInstr(i, osr_entry);
     param->set_ssa_temp_index(alloc_ssa_temp_index());
     AddToInitialDefinitions(osr_entry, param);
     (*env)[i] = param;
   }
-  // For OSR on a non-emtpy stack, insert synthetic phis on the joining entry.
-  // These phis are synthetic since they are not driven by live variable
-  // analysis, but merely serve the purpose of merging stack slots from
-  // parameters and other predecessors at the block in which OSR occurred.
-  JoinEntryInstr* join =
-      osr_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry();
-  ASSERT(join != nullptr);
-  for (intptr_t i = variable_count(); i < parameter_count; i++) {
-    PhiInstr* phi = join->InsertPhi(i, parameter_count);
-    phi->mark_alive();
-  }
 }
 
 void FlowGraph::PopulateEnvironmentFromCatchEntry(
@@ -1292,6 +1289,8 @@
         ASSERT(push_arg->IsPushArgument());
         ASSERT(reaching_defn->ssa_temp_index() != -1);
         ASSERT(reaching_defn->IsPhi());
+        push_arg->ReplaceUsesWith(push_arg->InputAt(0)->definition());
+        push_arg->UnuseAllInputs();
         push_arg->previous()->LinkTo(push_arg->next());
         push_arg->set_previous(nullptr);
         push_arg->set_next(nullptr);
@@ -1395,6 +1394,13 @@
         env->Add(current->Cast<PushArgumentInstr>());
         continue;
 
+      case Instruction::kCheckStackOverflow:
+        // Assert environment integrity at checkpoints.
+        ASSERT((variable_count() +
+                current->AsCheckStackOverflow()->stack_depth()) ==
+               env->length());
+        continue;
+
       default:
         // Other definitions directly go into the environment.
         if (Definition* definition = current->AsDefinition()) {
@@ -1417,10 +1423,23 @@
   }
 
   // 3. Process dominated blocks.
+  BlockEntryInstr* osr_succ =
+      (block_entry == graph_entry() && IsCompiledForOsr())
+          ? graph_entry()->osr_entry()->last_instruction()->SuccessorAt(0)
+          : nullptr;
   for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) {
     BlockEntryInstr* block = block_entry->dominated_blocks()[i];
     GrowableArray<Definition*> new_env(env->length());
     new_env.AddArray(*env);
+    ASSERT(block != nullptr);
+    if (block == osr_succ) {
+      // During OSR, when visiting the successor block of the OSR entry from
+      // the graph entry (rather than going through the OSR entry first), we
+      // must adjust the environment to mimic a non-empty incoming expression
+      // stack to ensure temporaries refer to the right stack items.
+      new_env.FillWith(constant_dead(), new_env.length(),
+                       graph_entry()->osr_entry()->stack_depth());
+    }
     RenameRecursive(block, &new_env, live_phis, variable_liveness,
                     inlining_parameters);
   }
@@ -1436,9 +1455,17 @@
     if (successor->phis() != NULL) {
       for (intptr_t i = 0; i < successor->phis()->length(); ++i) {
         PhiInstr* phi = (*successor->phis())[i];
-        if (phi != NULL) {
+        if (phi != nullptr) {
           // Rename input operand.
-          Value* use = new (zone()) Value((*env)[i]);
+          Definition* input = (*env)[i];
+          ASSERT(input != nullptr);
+          if (input->IsPushArgument()) {
+            // A push argument left on expression stack
+            // requires the variable name in SSA phis.
+            ASSERT(IsCompiledForOsr());
+            input = input->InputAt(0)->definition();
+          }
+          Value* use = new (zone()) Value(input);
           phi->SetInputAt(pred_index, use);
         }
       }
diff --git a/runtime/vm/compiler/backend/flow_graph_checker.cc b/runtime/vm/compiler/backend/flow_graph_checker.cc
index bde8521..54a3630 100644
--- a/runtime/vm/compiler/backend/flow_graph_checker.cc
+++ b/runtime/vm/compiler/backend/flow_graph_checker.cc
@@ -325,6 +325,10 @@
   } else {
     ASSERT(instruction->InputAt(use->use_index()) == use);
   }
+  // Make sure the reaching type, if any, has an owner consistent with this use.
+  if (auto const type = use->reaching_type()) {
+    ASSERT(type->owner() == nullptr || type->owner() == def);
+  }
   // Make sure each use appears in the graph and is properly dominated
   // by the definition (note that the proper dominance relation on the
   // input values of Phis is checked by the Phi visitor below).
@@ -368,6 +372,7 @@
   ASSERT(phi->InputCount() == current_block_->PredecessorCount());
   for (intptr_t i = 0, n = phi->InputCount(); i < n; ++i) {
     Definition* def = phi->InputAt(i)->definition();
+    ASSERT(def->HasSSATemp());  // phis have SSA defs
     BlockEntryInstr* edge = current_block_->PredecessorAt(i);
     ASSERT(DefDominatesUse(def, edge->last_instruction()));
   }
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 49597bb9..27600c2 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -722,12 +722,11 @@
 void FlowGraphCompiler::AddExceptionHandler(intptr_t try_index,
                                             intptr_t outer_try_index,
                                             intptr_t pc_offset,
-                                            TokenPosition token_pos,
                                             bool is_generated,
                                             const Array& handler_types,
                                             bool needs_stacktrace) {
   exception_handlers_list_->AddHandler(try_index, outer_try_index, pc_offset,
-                                       token_pos, is_generated, handler_types,
+                                       is_generated, handler_types,
                                        needs_stacktrace);
 }
 
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index f07d8d7..4c26d2b 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -730,7 +730,6 @@
   void AddExceptionHandler(intptr_t try_index,
                            intptr_t outer_try_index,
                            intptr_t pc_offset,
-                           TokenPosition token_pos,
                            bool is_generated,
                            const Array& handler_types,
                            bool needs_stacktrace);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index af3e2f5..7db6c39 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());
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index 8c9f45d..2e8362a 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());
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index 5b1a9c3..f311a34 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();
   }
 }
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 78987ee..fe4eace 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());
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index e3479a4..2b1152a 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -767,6 +767,30 @@
   return TargetAt(0)->exactness;
 }
 
+const char* AssertAssignableInstr::KindToCString(Kind kind) {
+  switch (kind) {
+#define KIND_CASE(name)                                                        \
+  case k##name:                                                                \
+    return #name;
+    FOR_EACH_ASSERT_ASSIGNABLE_KIND(KIND_CASE)
+#undef KIND_CASE
+    default:
+      UNREACHABLE();
+      return nullptr;
+  }
+}
+
+bool AssertAssignableInstr::ParseKind(const char* str, Kind* out) {
+#define KIND_CASE(name)                                                        \
+  if (strcmp(str, #name) == 0) {                                               \
+    *out = Kind::k##name;                                                      \
+    return true;                                                               \
+  }
+  FOR_EACH_ASSERT_ASSIGNABLE_KIND(KIND_CASE)
+#undef KIND_CASE
+  return false;
+}
+
 CheckClassInstr::CheckClassInstr(Value* value,
                                  intptr_t deopt_id,
                                  const Cids& cids,
@@ -1027,8 +1051,38 @@
     : value_(value), token_pos_(token_pos) {
   // Check that the value is not an incorrect Integer representation.
   ASSERT(!value.IsMint() || !Smi::IsValid(Mint::Cast(value).AsInt64Value()));
+  // Check that clones of fields are not stored as constants.
   ASSERT(!value.IsField() || Field::Cast(value).IsOriginal());
+  // Check that all non-Smi objects are heap allocated and in old space.
   ASSERT(value.IsSmi() || value.IsOld());
+#if defined(DEBUG)
+  // Generally, instances in the flow graph should be canonical. Smis and
+  // null values are canonical by construction and so we skip them here.
+  if (!value.IsNull() && !value.IsSmi() && value.IsInstance() &&
+      !value.IsCanonical()) {
+    // The only allowed type for which IsCanonical() never answers true is
+    // TypeParameter. (They are treated as canonical due to how they are
+    // created, but there is no way to canonicalize a new TypeParameter
+    // instance containing the same information as an existing instance.)
+    //
+    // Arrays in ConstantInstrs are usually immutable and canonicalized, but
+    // there are at least a couple of cases where one or both is not true:
+    //
+    // * The Arrays created as backing for ArgumentsDescriptors may not be
+    //   canonicalized for space reasons when inlined in the IL. However, they
+    //   are still immutable.
+    // * The backtracking stack for IRRegExps is put into a ConstantInstr for
+    //   immediate use as an argument to the operations on that stack. In this
+    //   case, the Array representing it is neither immutable or canonical.
+    //
+    // In addition to complicating the story for Arrays, IRRegExp compilation
+    // also uses other non-canonical values as "constants". For example, the bit
+    // tables used for certain character classes are represented as TypedData,
+    // and so those values are also neither immutable (as there are no immutable
+    // TypedData values) or canonical.
+    ASSERT(value.IsTypeParameter() || value.IsArray() || value.IsTypedData());
+  }
+#endif
 }
 
 bool ConstantInstr::AttributesEqual(Instruction* other) const {
@@ -1302,8 +1356,7 @@
   } else if (this == def->env_use_list()) {
     def->set_env_use_list(next);
     if (next != NULL) next->set_previous_use(NULL);
-  } else {
-    Value* prev = previous_use();
+  } else if (Value* prev = previous_use()) {
     prev->set_next_use(next);
     if (next != NULL) next->set_previous_use(prev);
   }
@@ -4283,8 +4336,8 @@
   return nullptr;
 }
 
-bool SpecialParameterInstr::KindFromCString(const char* str,
-                                            SpecialParameterKind* out) {
+bool SpecialParameterInstr::ParseKind(const char* str,
+                                      SpecialParameterKind* out) {
   ASSERT(str != nullptr && out != nullptr);
 #define KIND_CASE(Name)                                                        \
   if (strcmp(str, #Name) == 0) {                                               \
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index fb2fc75..8128fb9 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -87,7 +87,12 @@
         reaching_type_(NULL) {}
 
   Definition* definition() const { return definition_; }
-  void set_definition(Definition* definition) { definition_ = definition; }
+  void set_definition(Definition* definition) {
+    definition_ = definition;
+    // Clone the reaching type if there was one and the owner no longer matches
+    // this value's definition.
+    SetReachingType(reaching_type_);
+  }
 
   Value* previous_use() const { return previous_use_; }
   void set_previous_use(Value* previous) { previous_use_ = previous; }
@@ -156,6 +161,7 @@
 
  private:
   friend class FlowGraphPrinter;
+  friend class FlowGraphDeserializer;  // For setting reaching_type_ directly.
 
   Definition* definition_;
   Value* previous_use_;
@@ -1862,8 +1868,7 @@
 
 class CatchBlockEntryInstr : public BlockEntryWithInitialDefs {
  public:
-  CatchBlockEntryInstr(TokenPosition handler_token_pos,
-                       bool is_generated,
+  CatchBlockEntryInstr(bool is_generated,
                        intptr_t block_id,
                        intptr_t try_index,
                        GraphEntryInstr* graph_entry,
@@ -1885,7 +1890,6 @@
         raw_exception_var_(raw_exception_var),
         raw_stacktrace_var_(raw_stacktrace_var),
         needs_stacktrace_(needs_stacktrace),
-        handler_token_pos_(handler_token_pos),
         is_generated_(is_generated) {}
 
   DECLARE_INSTRUCTION(CatchBlockEntry)
@@ -1911,7 +1915,6 @@
   bool needs_stacktrace() const { return needs_stacktrace_; }
 
   bool is_generated() const { return is_generated_; }
-  TokenPosition handler_token_pos() const { return handler_token_pos_; }
 
   // Returns try index for the try block to which this catch handler
   // corresponds.
@@ -1938,7 +1941,6 @@
   const LocalVariable* raw_exception_var_;
   const LocalVariable* raw_stacktrace_var_;
   const bool needs_stacktrace_;
-  TokenPosition handler_token_pos_;
   bool is_generated_;
 
   DISALLOW_COPY_AND_ASSIGN(CatchBlockEntryInstr);
@@ -3269,7 +3271,18 @@
 
 class AssertAssignableInstr : public TemplateDefinition<3, Throws, Pure> {
  public:
-  enum Kind { kParameterCheck, kInsertedByFrontend, kFromSource, kUnknown };
+#define FOR_EACH_ASSERT_ASSIGNABLE_KIND(V)                                     \
+  V(ParameterCheck)                                                            \
+  V(InsertedByFrontend)                                                        \
+  V(FromSource)                                                                \
+  V(Unknown)
+
+#define KIND_DEFN(name) k##name,
+  enum Kind { FOR_EACH_ASSERT_ASSIGNABLE_KIND(KIND_DEFN) };
+#undef KIND_DEFN
+
+  static const char* KindToCString(Kind kind);
+  static bool ParseKind(const char* str, Kind* out);
 
   AssertAssignableInstr(TokenPosition token_pos,
                         Value* value,
@@ -3326,6 +3339,7 @@
   virtual Value* RedefinedValue() const;
 
   PRINT_OPERANDS_TO_SUPPORT
+  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
   const TokenPosition token_pos_;
@@ -3385,7 +3399,7 @@
 #undef KIND_INC
 
   static const char* KindToCString(SpecialParameterKind k);
-  static bool KindFromCString(const char* str, SpecialParameterKind* out);
+  static bool ParseKind(const char* str, SpecialParameterKind* out);
 
   SpecialParameterInstr(SpecialParameterKind kind,
                         intptr_t deopt_id,
@@ -3666,6 +3680,7 @@
 
   PRINT_OPERANDS_TO_SUPPORT
   ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
+  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
   bool MatchesCoreName(const String& name);
 
@@ -4438,6 +4453,7 @@
 
   PRINT_OPERANDS_TO_SUPPORT
   ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
+  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
   void set_native_c_function(NativeFunction value) {
@@ -5512,6 +5528,8 @@
     return other->AsLoadUntagged()->offset_ == offset_;
   }
 
+  PRINT_OPERANDS_TO_SUPPORT
+
  private:
   intptr_t offset_;
 
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 6f00a18..b6e2166 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);
 }
 
@@ -3237,10 +3239,9 @@
 
 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   __ Bind(compiler->GetJumpLabel(this));
-  compiler->AddExceptionHandler(catch_try_index(), try_index(),
-                                compiler->assembler()->CodeSize(),
-                                handler_token_pos(), is_generated(),
-                                catch_handler_types_, needs_stacktrace());
+  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());
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 3359f05..74c983d 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);
 }
 
@@ -2861,10 +2863,9 @@
 
 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   __ Bind(compiler->GetJumpLabel(this));
-  compiler->AddExceptionHandler(catch_try_index(), try_index(),
-                                compiler->assembler()->CodeSize(),
-                                handler_token_pos(), is_generated(),
-                                catch_handler_types_, needs_stacktrace());
+  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());
diff --git a/runtime/vm/compiler/backend/il_dbc.cc b/runtime/vm/compiler/backend/il_dbc.cc
index 7ac0079..bd859e9 100644
--- a/runtime/vm/compiler/backend/il_dbc.cc
+++ b/runtime/vm/compiler/backend/il_dbc.cc
@@ -1245,10 +1245,9 @@
 
 EMIT_NATIVE_CODE(CatchBlockEntry, 0) {
   __ Bind(compiler->GetJumpLabel(this));
-  compiler->AddExceptionHandler(catch_try_index(), try_index(),
-                                compiler->assembler()->CodeSize(),
-                                handler_token_pos(), is_generated(),
-                                catch_handler_types_, needs_stacktrace());
+  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());
@@ -1455,7 +1454,7 @@
 void Environment::DropArguments(intptr_t argc) {
 #if defined(DEBUG)
   // Check that we are in the backend - register allocation has been run.
-  ASSERT(locations_ != NULL);
+  ASSERT((Length() == 0) || (locations_ != nullptr));
 
   // Check that we are only dropping a valid number of instructions from the
   // environment.
diff --git a/runtime/vm/compiler/backend/il_deserializer.cc b/runtime/vm/compiler/backend/il_deserializer.cc
index f4bf535..97a98b1 100644
--- a/runtime/vm/compiler/backend/il_deserializer.cc
+++ b/runtime/vm/compiler/backend/il_deserializer.cc
@@ -44,6 +44,15 @@
   THR_Print("Results of round trip serialization: {\"function\":\"%s\"",
             results.function.ToFullyQualifiedCString());
   THR_Print(",\"success\":%s", results.success ? "true" : "false");
+
+  // 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);
+  // If we failed, then either there are unhandled instructions or we have
+  // an appropriate error message and sexp from the FlowGraphDeserializer.
+  ASSERT(results.success || !results.unhandled.is_empty() ||
+         (results.error_message != nullptr && results.error_sexp != nullptr));
+
   if (!results.unhandled.is_empty()) {
     CStringMap<intptr_t> count_map(zone);
     for (auto inst : results.unhandled) {
@@ -146,7 +155,7 @@
     } else {
       if (FLAG_trace_round_trip_serialization) {
         THR_Print("Successfully deserialized graph for %s\n",
-                  results.serialized->AsList()->At(0)->AsSymbol()->value());
+                  results.serialized->AsList()->At(1)->AsSymbol()->value());
       }
       results.success = true;
     }
@@ -256,9 +265,20 @@
     pos++;
   }
 
+  // The graph entry doesn't push any arguments onto the stack. Adding a
+  // pushed_stack_map_ entry for it allows us to unify how function entries
+  // are handled vs. other types of blocks with regards to incoming pushed
+  // argument stacks.
+  //
+  // We add this entry now so that ParseEnvironment can assume that there's
+  // always a current pushed_stack_map_ for current_block_.
+  auto const empty_stack = new (zone()) PushStack(zone(), 0);
+  pushed_stack_map_.Insert(0, empty_stack);
+
   // The deopt environment for the graph entry may use entries from the
   // constant pool, so that must be parsed first.
   if (auto const env_sexp = CheckList(root->ExtraLookupValue("env"))) {
+    current_block_ = graph;
     auto const env = ParseEnvironment(env_sexp);
     if (env == nullptr) return nullptr;
     env->DeepCopyTo(zone(), graph);
@@ -293,13 +313,6 @@
     block_worklist.Add(normal_entry->block_id());
   }
 
-  // The graph entry doesn't push any arguments onto the stack. Adding a
-  // pushed_stack_map_ entry for it allows us to unify how function entries
-  // are handled vs. other types of blocks with regards to incoming pushed
-  // argument stacks.
-  auto const empty_stack = new (zone()) PushStack(zone(), 0);
-  pushed_stack_map_.Insert(0, empty_stack);
-
   if (!ParseBlocks(root, pos, &block_worklist)) return nullptr;
 
   // Before we return the new graph, make sure all definitions were found for
@@ -307,10 +320,9 @@
   if (values_map_.Length() > 0) {
     auto it = values_map_.GetIterator();
     auto const kv = it.Next();
-    // TODO(sstrickl): This assumes SSA variables.
-    auto const sym =
-        new (zone()) SExpSymbol(OS::SCreate(zone(), "v%" Pd "", kv->key));
-    StoreError(sym, "no definition found for variable index in flow graph");
+    ASSERT(kv->value->length() > 0);
+    const auto& value_info = kv->value->At(0);
+    StoreError(value_info.sexp, "no definition found for use in flow graph");
     return nullptr;
   }
 
@@ -336,6 +348,14 @@
   // Since we will not be adding new definitions, we make the initial size of
   // the worklist the number of definitions in the constant pool.
   GrowableArray<SExpList*> worklist(zone(), pool->Length() - 1);
+  // In order to ensure that the definition order is the same in the original
+  // flow graph, we can't just simply call GetConstant() whenever we
+  // successfully parse a constant. Instead, we'll create a stand-in
+  // ConstantInstr that we can temporarily stick in the definition_map_, and
+  // then once finished we'll go back through, add the constants via
+  // GetConstant() and parse any extra information.
+  DirectChainedHashMap<RawPointerKeyValueTrait<SExpList, ConstantInstr*>>
+      parsed_constants(zone());
   // We keep old_worklist in reverse order so that we can just RemoveLast
   // to get elements in their original order.
   for (intptr_t i = pool->Length() - 1; i > 0; i--) {
@@ -353,8 +373,16 @@
         parse_failures.Add(def_sexp);
         continue;
       }
-      ConstantInstr* def = flow_graph_->GetConstant(obj);
-      if (!ParseDefinitionWithParsedBody(def_sexp, def)) return false;
+      ConstantInstr* def = new (zone()) ConstantInstr(obj);
+      // Instead of parsing the whole definition, just get the SSA index so
+      // we can insert it into the definition_map_.
+      intptr_t index;
+      auto const name_sexp = CheckSymbol(Retrieve(def_sexp, 1));
+      if (!ParseSSATemp(name_sexp, &index)) return false;
+      def->set_ssa_temp_index(index);
+      ASSERT(!definition_map_.HasKey(index));
+      definition_map_.Insert(index, def);
+      parsed_constants.Insert({def_sexp, def});
     }
     if (parse_failures.is_empty()) break;
     // We've gone through the whole worklist without success, so return
@@ -366,6 +394,20 @@
       worklist.Add(parse_failures.RemoveLast());
     }
   }
+  // Now loop back through the constant pool definition S-expressions and
+  // get the real ConstantInstrs the flow graph will be using and finish
+  // parsing.
+  for (intptr_t i = 1; i < pool->Length(); i++) {
+    auto const def_sexp = CheckTaggedList(pool->At(i));
+    auto const temp_def = parsed_constants.LookupValue(def_sexp);
+    ASSERT(temp_def != nullptr);
+    // Remove the temporary definition from definition_map_ so this doesn't get
+    // flagged as a redefinition.
+    definition_map_.Remove(temp_def->ssa_temp_index());
+    ConstantInstr* real_def = flow_graph_->GetConstant(temp_def->value());
+    if (!ParseDefinitionWithParsedBody(def_sexp, real_def)) return false;
+    ASSERT(temp_def->ssa_temp_index() == real_def->ssa_temp_index());
+  }
   return true;
 }
 
@@ -383,7 +425,7 @@
       StoreError(entry->At(1), "multiple entries for block found");
       return false;
     }
-    const auto tag = entry->At(0)->AsSymbol();
+    const auto tag = entry->Tag();
     if (ParseBlockHeader(entry, block_id, tag) == nullptr) return false;
   }
   return true;
@@ -622,7 +664,7 @@
     auto const entry = CheckTaggedList(Retrieve(list, i));
     if (entry == nullptr) return false;
     Instruction* inst = nullptr;
-    if (strcmp(entry->At(0)->AsSymbol()->value(), "def") == 0) {
+    if (entry->Tag()->Equals("def")) {
       inst = ParseDefinition(entry);
     } else {
       inst = ParseInstruction(entry);
@@ -673,7 +715,7 @@
   }
 
   definition_map_.Insert(index, def);
-  FixPendingValues(index, def);
+  if (!FixPendingValues(index, def)) return false;
   return true;
 }
 
@@ -692,13 +734,18 @@
 
 Instruction* FlowGraphDeserializer::ParseInstruction(SExpList* list) {
   if (list == nullptr) return nullptr;
-  auto const tag = list->At(0)->AsSymbol();
+  auto const tag = list->Tag();
 
   intptr_t deopt_id = DeoptId::kNone;
   if (auto const deopt_int = CheckInteger(list->ExtraLookupValue("deopt_id"))) {
     deopt_id = deopt_int->value();
   }
-  InstrInfo common_info = {deopt_id, TokenPosition::kNoSource};
+  TokenPosition token_pos = TokenPosition::kNoSource;
+  if (auto const token_int =
+          CheckInteger(list->ExtraLookupValue("token_pos"))) {
+    token_pos = TokenPosition(token_int->value());
+  }
+  InstrInfo common_info = {deopt_id, token_pos};
 
   // Parse the environment before handling the instruction, as we may have
   // references to PushArguments and parsing the instruction may pop
@@ -777,7 +824,7 @@
     const InstrInfo& info) {
   auto& cls = Class::ZoneHandle(zone());
   auto const cls_sexp = CheckTaggedList(Retrieve(sexp, 1), "Class");
-  if (!ParseDartValue(cls_sexp, &cls)) return nullptr;
+  if (!ParseClass(cls_sexp, &cls)) return nullptr;
 
   intptr_t args_len = 0;
   if (auto const len_sexp = CheckInteger(sexp->ExtraLookupValue("args_len"))) {
@@ -792,13 +839,64 @@
   if (auto const closure_sexp = CheckTaggedList(
           sexp->ExtraLookupValue("closure_function"), "Function")) {
     auto& closure_function = Function::Handle(zone());
-    if (!ParseDartValue(closure_sexp, &closure_function)) return nullptr;
+    if (!ParseFunction(closure_sexp, &closure_function)) return nullptr;
     inst->set_closure_function(closure_function);
   }
 
   return inst;
 }
 
+AssertAssignableInstr* FlowGraphDeserializer::DeserializeAssertAssignable(
+    SExpList* sexp,
+    const InstrInfo& info) {
+  auto const val = ParseValue(Retrieve(sexp, 1));
+  if (val == nullptr) return nullptr;
+
+  auto const inst_type_args = ParseValue(Retrieve(sexp, 2));
+  if (inst_type_args == nullptr) return nullptr;
+
+  auto const func_type_args = ParseValue(Retrieve(sexp, 3));
+  if (func_type_args == nullptr) return nullptr;
+
+  auto& dst_type = AbstractType::Handle(zone());
+  auto const dst_type_sexp = Retrieve(sexp, "type");
+  if (!ParseDartValue(dst_type_sexp, &dst_type)) return nullptr;
+
+  auto& dst_name = String::ZoneHandle(zone());
+  auto const dst_name_sexp = Retrieve(sexp, "name");
+  if (!ParseDartValue(dst_name_sexp, &dst_name)) return nullptr;
+
+  auto kind = AssertAssignableInstr::Kind::kUnknown;
+  if (auto const kind_sexp = CheckSymbol(sexp->ExtraLookupValue("kind"))) {
+    if (!AssertAssignableInstr::ParseKind(kind_sexp->value(), &kind)) {
+      StoreError(kind_sexp, "unknown AssertAssignable kind");
+      return nullptr;
+    }
+  }
+
+  return new (zone())
+      AssertAssignableInstr(info.token_pos, val, inst_type_args, func_type_args,
+                            dst_type, dst_name, info.deopt_id, kind);
+}
+
+AssertBooleanInstr* FlowGraphDeserializer::DeserializeAssertBoolean(
+    SExpList* sexp,
+    const InstrInfo& info) {
+  auto const val = ParseValue(Retrieve(sexp, 1));
+  if (val == nullptr) return nullptr;
+
+  return new (zone()) AssertBooleanInstr(info.token_pos, val, info.deopt_id);
+}
+
+BooleanNegateInstr* FlowGraphDeserializer::DeserializeBooleanNegate(
+    SExpList* sexp,
+    const InstrInfo& info) {
+  auto const value = ParseValue(Retrieve(sexp, 1));
+  if (value == nullptr) return nullptr;
+
+  return new (zone()) BooleanNegateInstr(value);
+}
+
 BranchInstr* FlowGraphDeserializer::DeserializeBranch(SExpList* sexp,
                                                       const InstrInfo& info) {
   auto const comp_sexp = CheckTaggedList(Retrieve(sexp, 1));
@@ -863,7 +961,7 @@
 
   auto kind = CheckStackOverflowInstr::kOsrAndPreemption;
   if (auto const kind_sexp = CheckSymbol(sexp->ExtraLookupValue("kind"))) {
-    ASSERT(strcmp(kind_sexp->value(), "OsrOnly") == 0);
+    ASSERT(kind_sexp->Equals("OsrOnly"));
     kind = CheckStackOverflowInstr::kOsrOnly;
   }
 
@@ -884,7 +982,7 @@
     const InstrInfo& info) {
   auto kind = RawPcDescriptors::kAnyKind;
   if (auto const kind_sexp = CheckSymbol(Retrieve(sexp, "stub_kind"))) {
-    if (!RawPcDescriptors::KindFromCString(kind_sexp->value(), &kind)) {
+    if (!RawPcDescriptors::ParseKind(kind_sexp->value(), &kind)) {
       StoreError(kind_sexp, "not a valid RawPcDescriptors::Kind name");
       return nullptr;
     }
@@ -903,6 +1001,67 @@
   return new (zone()) GotoInstr(block->AsJoinEntry(), info.deopt_id);
 }
 
+InstanceCallInstr* FlowGraphDeserializer::DeserializeInstanceCall(
+    SExpList* sexp,
+    const InstrInfo& info) {
+  auto& interface_target = Function::ZoneHandle(zone());
+  if (!ParseDartValue(Retrieve(sexp, 1), &interface_target)) return nullptr;
+
+  auto& function_name = String::ZoneHandle(zone());
+  // If we have an explicit function_name value, then use that value. Otherwise,
+  // if we have an non-null interface_target, use its name.
+  if (auto const name_sexp = sexp->ExtraLookupValue("function_name")) {
+    if (!ParseDartValue(name_sexp, &function_name)) return nullptr;
+  } else if (!interface_target.IsNull()) {
+    function_name = interface_target.name();
+  }
+
+  auto token_kind = Token::Kind::kILLEGAL;
+  if (auto const kind_sexp =
+          CheckSymbol(sexp->ExtraLookupValue("token_kind"))) {
+    if (!Token::FromStr(kind_sexp->value(), &token_kind)) {
+      StoreError(kind_sexp, "unexpected token kind");
+      return nullptr;
+    }
+  }
+
+  CallInfo call_info(zone());
+  if (!ParseCallInfo(sexp, &call_info)) return nullptr;
+
+  intptr_t checked_arg_count = 0;
+  if (auto const checked_sexp =
+          CheckInteger(sexp->ExtraLookupValue("checked_arg_count"))) {
+    checked_arg_count = checked_sexp->value();
+  }
+
+  auto const inst = new (zone()) InstanceCallInstr(
+      info.token_pos, function_name, token_kind, call_info.arguments,
+      call_info.type_args_len, call_info.argument_names, checked_arg_count,
+      info.deopt_id, interface_target);
+
+  if (call_info.result_type != nullptr) {
+    inst->SetResultType(zone(), *call_info.result_type);
+  }
+
+  inst->set_entry_kind(call_info.entry_kind);
+
+  if (auto const ic_data_sexp =
+          CheckTaggedList(Retrieve(sexp, "ic_data"), "ICData")) {
+    if (!CreateICData(ic_data_sexp, inst)) return nullptr;
+  }
+
+  return inst;
+}
+
+LoadClassIdInstr* FlowGraphDeserializer::DeserializeLoadClassId(
+    SExpList* sexp,
+    const InstrInfo& info) {
+  auto const val = ParseValue(Retrieve(sexp, 1));
+  if (val == nullptr) return nullptr;
+
+  return new (zone()) LoadClassIdInstr(val);
+}
+
 LoadFieldInstr* FlowGraphDeserializer::DeserializeLoadField(
     SExpList* sexp,
     const InstrInfo& info) {
@@ -915,6 +1074,33 @@
   return new (zone()) LoadFieldInstr(instance, *slot, info.token_pos);
 }
 
+NativeCallInstr* FlowGraphDeserializer::DeserializeNativeCall(
+    SExpList* sexp,
+    const InstrInfo& info) {
+  auto& function = Function::ZoneHandle(zone());
+  if (!ParseDartValue(Retrieve(sexp, 1), &function)) return nullptr;
+  if (!function.IsFunction()) {
+    StoreError(sexp->At(1), "expected a Function value");
+    return nullptr;
+  }
+
+  auto const name_sexp = CheckString(Retrieve(sexp, "name"));
+  if (name_sexp == nullptr) return nullptr;
+  const auto& name =
+      String::ZoneHandle(zone(), String::New(name_sexp->value()));
+
+  bool link_lazily = false;
+  if (auto const link_sexp = CheckBool(sexp->ExtraLookupValue("link_lazily"))) {
+    link_lazily = link_sexp->value();
+  }
+
+  CallInfo call_info(zone());
+  if (!ParseCallInfo(sexp, &call_info)) return nullptr;
+
+  return new (zone()) NativeCallInstr(&name, &function, link_lazily,
+                                      info.token_pos, call_info.arguments);
+}
+
 ParameterInstr* FlowGraphDeserializer::DeserializeParameter(
     SExpList* sexp,
     const InstrInfo& info) {
@@ -951,7 +1137,7 @@
   auto const kind_sexp = CheckSymbol(Retrieve(sexp, 1));
   if (kind_sexp == nullptr) return nullptr;
   SpecialParameterInstr::SpecialParameterKind kind;
-  if (!SpecialParameterInstr::KindFromCString(kind_sexp->value(), &kind)) {
+  if (!SpecialParameterInstr::ParseKind(kind_sexp->value(), &kind)) {
     StoreError(kind_sexp, "unknown special parameter kind");
     return nullptr;
   }
@@ -964,37 +1150,10 @@
     const InstrInfo& info) {
   auto& function = Function::ZoneHandle(zone());
   auto const function_sexp = CheckTaggedList(Retrieve(sexp, 1), "Function");
-  if (!ParseDartValue(function_sexp, &function)) return nullptr;
+  if (!ParseFunction(function_sexp, &function)) return nullptr;
 
-  intptr_t type_args_len = 0;
-  if (auto const type_args_len_sexp =
-          CheckInteger(sexp->ExtraLookupValue("type_args_len"))) {
-    type_args_len = type_args_len_sexp->value();
-  }
-
-  Array& argument_names = Array::ZoneHandle(zone());
-  if (auto const arg_names_sexp =
-          CheckList(sexp->ExtraLookupValue("arg_names"))) {
-    argument_names = Array::New(arg_names_sexp->Length(), Heap::kOld);
-    for (intptr_t i = 0, n = arg_names_sexp->Length(); i < n; i++) {
-      auto name_sexp = CheckString(Retrieve(arg_names_sexp, i));
-      if (name_sexp == nullptr) return nullptr;
-      tmp_string_ = String::New(name_sexp->value(), Heap::kOld);
-      argument_names.SetAt(i, tmp_string_);
-    }
-  }
-
-  intptr_t args_len = 0;
-  if (auto const args_len_sexp =
-          CheckInteger(sexp->ExtraLookupValue("args_len"))) {
-    args_len = args_len_sexp->value();
-  }
-
-  // Type arguments are wrapped in a TypeArguments array, so no matter how
-  // many there are, they are contained in a single pushed argument.
-  auto const all_args_len = (type_args_len > 0 ? 1 : 0) + args_len;
-  auto const arguments = FetchPushedArguments(sexp, all_args_len);
-  if (arguments == nullptr) return nullptr;
+  CallInfo call_info(zone());
+  if (!ParseCallInfo(sexp, &call_info)) return nullptr;
 
   intptr_t call_count = 0;
   if (auto const call_count_sexp =
@@ -1002,18 +1161,32 @@
     call_count = call_count_sexp->value();
   }
 
-  auto rebind_rule = ICData::kInstance;
+  auto rebind_rule = ICData::kStatic;
   if (auto const rebind_sexp =
           CheckSymbol(sexp->ExtraLookupValue("rebind_rule"))) {
-    if (!ICData::RebindRuleFromCString(rebind_sexp->value(), &rebind_rule)) {
+    if (!ICData::ParseRebindRule(rebind_sexp->value(), &rebind_rule)) {
       StoreError(rebind_sexp, "unknown rebind rule value");
       return nullptr;
     }
   }
 
-  return new (zone())
-      StaticCallInstr(info.token_pos, function, type_args_len, argument_names,
-                      arguments, info.deopt_id, call_count, rebind_rule);
+  auto const inst = new (zone())
+      StaticCallInstr(info.token_pos, function, call_info.type_args_len,
+                      call_info.argument_names, call_info.arguments,
+                      info.deopt_id, call_count, rebind_rule);
+
+  if (call_info.result_type != nullptr) {
+    inst->SetResultType(zone(), *call_info.result_type);
+  }
+
+  inst->set_entry_kind(call_info.entry_kind);
+
+  if (auto const ic_data_sexp =
+          CheckTaggedList(sexp->ExtraLookupValue("ic_data"), "ICData")) {
+    if (!CreateICData(ic_data_sexp, inst)) return nullptr;
+  }
+
+  return inst;
 }
 
 StoreInstanceFieldInstr* FlowGraphDeserializer::DeserializeStoreInstanceField(
@@ -1067,18 +1240,74 @@
                                          needs_check, info.deopt_id);
 }
 
+ThrowInstr* FlowGraphDeserializer::DeserializeThrow(SExpList* sexp,
+                                                    const InstrInfo& info) {
+  return new (zone()) ThrowInstr(info.token_pos, info.deopt_id);
+}
+
+bool FlowGraphDeserializer::ParseCallInfo(SExpList* call, CallInfo* out) {
+  ASSERT(out != nullptr);
+
+  if (auto const len_sexp =
+          CheckInteger(call->ExtraLookupValue("type_args_len"))) {
+    out->type_args_len = len_sexp->value();
+  }
+
+  if (auto const arg_names_sexp =
+          CheckList(call->ExtraLookupValue("arg_names"))) {
+    out->argument_names = Array::New(arg_names_sexp->Length(), Heap::kOld);
+    for (intptr_t i = 0, n = arg_names_sexp->Length(); i < n; i++) {
+      auto name_sexp = CheckString(Retrieve(arg_names_sexp, i));
+      if (name_sexp == nullptr) return false;
+      tmp_string_ = String::New(name_sexp->value(), Heap::kOld);
+      out->argument_names.SetAt(i, tmp_string_);
+    }
+  }
+
+  if (auto const args_len_sexp =
+          CheckInteger(call->ExtraLookupValue("args_len"))) {
+    out->args_len = args_len_sexp->value();
+  }
+
+  if (auto const result_sexp = CheckTaggedList(
+          call->ExtraLookupValue("result_type"), "CompileType")) {
+    out->result_type = ParseCompileType(result_sexp);
+  }
+
+  if (auto const kind_sexp =
+          CheckSymbol(call->ExtraLookupValue("entry_kind"))) {
+    if (!Code::ParseEntryKind(kind_sexp->value(), &out->entry_kind))
+      return false;
+  }
+
+  // Type arguments are wrapped in a TypeArguments array, so no matter how
+  // many there are, they are contained in a single pushed argument.
+  auto const all_args_len = (out->type_args_len > 0 ? 1 : 0) + out->args_len;
+  out->arguments = FetchPushedArguments(call, all_args_len);
+  if (out->arguments == nullptr) return false;
+
+  return true;
+}
+
 Value* FlowGraphDeserializer::ParseValue(SExpression* sexp,
                                          bool allow_pending) {
-  auto name = sexp->AsSymbol();
   CompileType* type = nullptr;
+  bool inherit_type = false;
+  auto name = sexp->AsSymbol();
   if (name == nullptr) {
     auto const list = CheckTaggedList(sexp, "value");
     name = CheckSymbol(Retrieve(list, 1));
-    if (name == nullptr) return nullptr;
     if (auto const type_sexp =
             CheckTaggedList(list->ExtraLookupValue("type"), "CompileType")) {
       type = ParseCompileType(type_sexp);
       if (type == nullptr) return nullptr;
+    } else if (auto const inherit_sexp =
+                   CheckBool(list->ExtraLookupValue("inherit_type"))) {
+      inherit_type = inherit_sexp->value();
+    } else {
+      // We assume that the type should be inherited from the definition for
+      // for (value ...) forms without an explicit type.
+      inherit_type = true;
     }
   }
   intptr_t index;
@@ -1090,9 +1319,17 @@
       StoreError(sexp, "found use prior to definition");
       return nullptr;
     }
-    val = AddNewPendingValue(index);
+    val = AddNewPendingValue(sexp, index, inherit_type);
   } else {
     val = new (zone()) Value(def);
+    if (inherit_type) {
+      if (def->HasType()) {
+        val->reaching_type_ = def->Type();
+      } else {
+        StoreError(sexp, "value inherits type, but no type found");
+        return nullptr;
+      }
+    }
   }
   if (type != nullptr) val->SetReachingType(type);
   return val;
@@ -1108,22 +1345,17 @@
                                       : CompileType::kNonNullable;
   }
 
-  // A cid as the second element means that the type is based off a concrete
-  // class.
-  intptr_t cid = kDynamicCid;
-  if (sexp->Length() > 1) {
-    if (auto const cid_sexp = CheckInteger(sexp->At(1))) {
-      // TODO(sstrickl): Check that the cid is a valid cid.
-      cid = cid_sexp->value();
-    } else {
-      return nullptr;
-    }
+  intptr_t cid = kIllegalCid;
+  if (auto const cid_sexp = CheckInteger(sexp->ExtraLookupValue("cid"))) {
+    // TODO(sstrickl): Check that the cid is a valid concrete cid, or a cid
+    // otherwise found in CompileTypes like kIllegalCid or kDynamicCid.
+    cid = cid_sexp->value();
   }
 
   AbstractType* type = nullptr;
-  if (auto const type_sexp = CheckTaggedList(sexp->ExtraLookupValue("type"))) {
+  if (auto const type_sexp = sexp->ExtraLookupValue("type")) {
     auto& type_handle = AbstractType::ZoneHandle(zone());
-    if (!ParseDartValue(type_sexp, &type_handle)) return nullptr;
+    if (!ParseAbstractType(type_sexp, &type_handle)) return nullptr;
     type = &type_handle;
   }
   return new (zone()) CompileType(nullable, cid, type);
@@ -1146,6 +1378,7 @@
     }
   }
 
+  ASSERT(parsed_function_ != nullptr);
   auto const env = new (zone()) Environment(list->Length(), fixed_param_count,
                                             *parsed_function_, outer_env);
 
@@ -1181,7 +1414,7 @@
   if (auto const sym = sexp->AsSymbol()) {
     // We'll use the null value in *out as a marker later, so go ahead and exit
     // early if we parse one.
-    if (strcmp(sym->value(), "null") == 0) return true;
+    if (sym->Equals("null")) return true;
 
     // The only other symbols that should appear in Dart value position are
     // names of constant definitions.
@@ -1199,126 +1432,7 @@
 
   // Other instance values may need to be canonicalized, so do that before
   // returning.
-  if (auto const list = CheckTaggedList(sexp)) {
-    auto const tag = list->At(0)->AsSymbol();
-    if (strcmp(tag->value(), "Class") == 0) {
-      auto const cid_sexp = CheckInteger(Retrieve(list, 1));
-      if (cid_sexp == nullptr) return false;
-      ClassTable* table = thread()->isolate()->class_table();
-      if (!table->HasValidClassAt(cid_sexp->value())) {
-        StoreError(cid_sexp, "no valid class found for cid");
-        return false;
-      }
-      *out = table->At(cid_sexp->value());
-    } else if (strcmp(tag->value(), "Type") == 0) {
-      if (const auto cls_sexp = CheckTaggedList(Retrieve(list, 1), "Class")) {
-        auto& cls = Class::ZoneHandle(zone());
-        if (!ParseDartValue(cls_sexp, &cls)) return false;
-        auto& type_args = TypeArguments::ZoneHandle(zone());
-        if (const auto ta_sexp = CheckTaggedList(
-                list->ExtraLookupValue("type_args"), "TypeArguments")) {
-          if (!ParseDartValue(ta_sexp, &type_args)) return false;
-        }
-        *out = Type::New(cls, type_args, TokenPosition::kNoSource, Heap::kOld);
-        // Need to set this for canonicalization. We ensure in the serializer
-        // that only finalized types are successfully serialized.
-        Type::Cast(*out).SetIsFinalized();
-      }
-      // TODO(sstrickl): Handle types not derived from classes.
-    } else if (strcmp(tag->value(), "TypeArguments") == 0) {
-      *out = TypeArguments::New(list->Length() - 1, Heap::kOld);
-      auto& type_args = TypeArguments::Cast(*out);
-      for (intptr_t i = 1, n = list->Length(); i < n; i++) {
-        if (!ParseDartValue(Retrieve(list, i), &value_type_)) return false;
-        type_args.SetTypeAt(i - 1, value_type_);
-      }
-    } else if (strcmp(tag->value(), "Field") == 0) {
-      auto const name_sexp = CheckSymbol(Retrieve(list, 1));
-      if (!ParseCanonicalName(name_sexp, out)) return false;
-    } else if (strcmp(tag->value(), "Function") == 0) {
-      auto const name_sexp = CheckSymbol(Retrieve(list, 1));
-      if (!ParseCanonicalName(name_sexp, out)) return false;
-      // Check the kind expected by the S-expression if one was specified.
-      if (auto const kind_sexp = CheckSymbol(list->ExtraLookupValue("kind"))) {
-        RawFunction::Kind kind;
-        if (!RawFunction::KindFromCString(kind_sexp->value(), &kind)) {
-          StoreError(kind_sexp, "unexpected function kind");
-          return false;
-        }
-        auto& function = Function::Cast(*out);
-        if (function.kind() != kind) {
-          auto const kind_str = RawFunction::KindToCString(function.kind());
-          StoreError(list, "retrieved function has kind %s", kind_str);
-          return false;
-        }
-      }
-    } else if (strcmp(tag->value(), "TypeParameter") == 0) {
-      ASSERT(parsed_function_ != nullptr);
-      auto const name_sexp = CheckSymbol(Retrieve(list, 1));
-      if (name_sexp == nullptr) return false;
-      const auto& func = parsed_function_->function();
-      tmp_string_ = String::New(name_sexp->value());
-      *out = func.LookupTypeParameter(tmp_string_, nullptr);
-      if (out->IsNull()) {
-        // Check the owning class for the function as well.
-        value_class_ = func.Owner();
-        *out = value_class_.LookupTypeParameter(tmp_string_);
-      }
-      // We'll want a more specific error message than the generic unhandled
-      // Dart value one if this failed.
-      if (out->IsNull()) {
-        StoreError(name_sexp, "no type parameter found for name");
-        return false;
-      }
-    } else if (strcmp(tag->value(), "ImmutableList") == 0) {
-      // Since arrays can contain arrays, we must allocate a new handle here.
-      auto& arr =
-          Array::Handle(zone(), Array::New(list->Length() - 1, Heap::kOld));
-      for (intptr_t i = 1; i < list->Length(); i++) {
-        if (!ParseDartValue(Retrieve(list, i), &value_object_)) return false;
-        arr.SetAt(i - 1, value_object_);
-      }
-      if (auto type_args_sexp = CheckTaggedList(
-              list->ExtraLookupValue("type_args"), "TypeArguments")) {
-        if (!ParseDartValue(type_args_sexp, &value_type_args_)) return false;
-        arr.SetTypeArguments(value_type_args_);
-      }
-      arr.MakeImmutable();
-      *out = arr.raw();
-    } else if (strcmp(tag->value(), "Instance") == 0) {
-      if (!ParseInstance(list, reinterpret_cast<Instance*>(out))) return false;
-    } else if (strcmp(tag->value(), "Closure") == 0) {
-      auto& function = Function::ZoneHandle(zone());
-      if (!ParseDartValue(Retrieve(list, 1), &function)) return false;
-
-      auto& context = Context::ZoneHandle(zone());
-      if (list->ExtraLookupValue("context") != nullptr) {
-        StoreError(list, "closures with contexts currently unhandled");
-        return false;
-      }
-
-      auto& inst_type_args = TypeArguments::ZoneHandle(zone());
-      if (auto const type_args_sexp = CheckTaggedList(
-              Retrieve(list, "inst_type_args"), "TypeArguments")) {
-        if (!ParseDartValue(type_args_sexp, &inst_type_args)) return false;
-      }
-
-      auto& func_type_args = TypeArguments::ZoneHandle(zone());
-      if (auto const type_args_sexp = CheckTaggedList(
-              Retrieve(list, "func_type_args"), "TypeArguments")) {
-        if (!ParseDartValue(type_args_sexp, &func_type_args)) return false;
-      }
-
-      auto& delayed_type_args = TypeArguments::ZoneHandle(zone());
-      if (auto const type_args_sexp = CheckTaggedList(
-              Retrieve(list, "delayed_type_args"), "TypeArguments")) {
-        if (!ParseDartValue(type_args_sexp, &delayed_type_args)) return false;
-      }
-
-      *out = Closure::New(inst_type_args, func_type_args, delayed_type_args,
-                          function, context, Heap::kOld);
-    }
-  } else if (auto const b = sexp->AsBool()) {
+  if (auto const b = sexp->AsBool()) {
     *out = Bool::Get(b->value()).raw();
   } else if (auto const str = sexp->AsString()) {
     *out = String::New(str->value(), Heap::kOld);
@@ -1326,6 +1440,29 @@
     *out = Integer::New(i->value(), Heap::kOld);
   } else if (auto const d = sexp->AsDouble()) {
     *out = Double::New(d->value(), Heap::kOld);
+  } else if (auto const list = CheckTaggedList(sexp)) {
+    auto const tag = list->Tag();
+    if (tag->Equals("Class")) {
+      return ParseClass(list, out);
+    } else if (tag->Equals("Type")) {
+      return ParseType(list, out);
+    } else if (tag->Equals("TypeArguments")) {
+      return ParseTypeArguments(list, out);
+    } else if (tag->Equals("Field")) {
+      return ParseField(list, out);
+    } else if (tag->Equals("Function")) {
+      return ParseFunction(list, out);
+    } else if (tag->Equals("TypeParameter")) {
+      return ParseTypeParameter(list, out);
+    } else if (tag->Equals("ImmutableList")) {
+      return ParseImmutableList(list, out);
+    } else if (tag->Equals("Instance")) {
+      return ParseInstance(list, out);
+    } else if (tag->Equals("Closure")) {
+      return ParseClosure(list, out);
+    } else if (tag->Equals("TypeRef")) {
+      return ParseTypeRef(list, out);
+    }
   }
 
   // If we're here and still haven't gotten a non-null value, then something
@@ -1335,26 +1472,170 @@
     return false;
   }
 
-  if (out->IsInstance()) {
-    const char* error_str = nullptr;
-    // CheckAndCanonicalize uses the current zone for the passed in thread,
-    // not an explicitly provided zone. This means we cannot be run in a context
-    // where [thread()->zone()] does not match [zone()] (e.g., due to StackZone)
-    // until this is addressed.
-    *out = Instance::Cast(*out).CheckAndCanonicalize(thread(), &error_str);
-    if (out->IsNull()) {
-      if (error_str != nullptr) {
-        StoreError(sexp, "error during canonicalization: %s", error_str);
-      } else {
-        StoreError(sexp, "unexpected error during canonicalization");
-      }
+  if (!out->IsInstance()) return true;
+  return CanonicalizeInstance(sexp, out);
+}
+
+bool FlowGraphDeserializer::CanonicalizeInstance(SExpression* sexp,
+                                                 Object* out) {
+  ASSERT(out != nullptr);
+  if (!out->IsInstance()) return true;
+  const char* error_str = nullptr;
+  // CheckAndCanonicalize uses the current zone for the passed in thread,
+  // not an explicitly provided zone. This means we cannot be run in a context
+  // where [thread()->zone()] does not match [zone()] (e.g., due to StackZone)
+  // until this is addressed.
+  *out = Instance::Cast(*out).CheckAndCanonicalize(thread(), &error_str);
+  if (error_str != nullptr) {
+    StoreError(sexp, "error during canonicalization: %s", error_str);
+    return false;
+  }
+  return true;
+}
+
+bool FlowGraphDeserializer::ParseAbstractType(SExpression* sexp, Object* out) {
+  ASSERT(out != nullptr);
+  if (sexp == nullptr) return false;
+
+  // If it's a symbol, it should be a reference to a constant definition, which
+  // is handled in ParseType.
+  if (auto const sym = sexp->AsSymbol()) {
+    return ParseType(sexp, out);
+  } else if (auto const list = CheckTaggedList(sexp)) {
+    auto const tag = list->Tag();
+    if (tag->Equals("Type")) {
+      return ParseType(list, out);
+    } else if (tag->Equals("TypeParameter")) {
+      return ParseTypeParameter(list, out);
+    } else if (tag->Equals("TypeRef")) {
+      return ParseTypeRef(list, out);
+    }
+  }
+
+  StoreError(sexp, "not an AbstractType");
+  return false;
+}
+
+bool FlowGraphDeserializer::ParseClass(SExpList* list, Object* out) {
+  ASSERT(out != nullptr);
+  if (list == nullptr) return false;
+
+  auto const ref_sexp = Retrieve(list, 1);
+  if (ref_sexp == nullptr) return false;
+  if (auto const cid_sexp = ref_sexp->AsInteger()) {
+    ClassTable* table = thread()->isolate()->class_table();
+    if (!table->HasValidClassAt(cid_sexp->value())) {
+      StoreError(cid_sexp, "no valid class found for cid");
+      return false;
+    }
+    *out = table->At(cid_sexp->value());
+  } else if (auto const name_sexp = ref_sexp->AsSymbol()) {
+    if (!ParseCanonicalName(name_sexp, out)) return false;
+    if (!out->IsClass()) {
+      StoreError(name_sexp, "expected the name of a class");
       return false;
     }
   }
   return true;
 }
 
-bool FlowGraphDeserializer::ParseInstance(SExpList* list, Instance* out) {
+bool FlowGraphDeserializer::ParseClosure(SExpList* list, Object* out) {
+  ASSERT(out != nullptr);
+  if (list == nullptr) return false;
+
+  auto& function = Function::ZoneHandle(zone());
+  auto const function_sexp = CheckTaggedList(Retrieve(list, 1), "Function");
+  if (!ParseFunction(function_sexp, &function)) return false;
+
+  auto& context = Context::ZoneHandle(zone());
+  if (list->ExtraLookupValue("context") != nullptr) {
+    StoreError(list, "closures with contexts currently unhandled");
+    return false;
+  }
+
+  auto& inst_type_args = TypeArguments::ZoneHandle(zone());
+  if (auto const type_args_sexp = Retrieve(list, "inst_type_args")) {
+    if (!ParseTypeArguments(type_args_sexp, &inst_type_args)) return false;
+  }
+
+  auto& func_type_args = TypeArguments::ZoneHandle(zone());
+  if (auto const type_args_sexp = Retrieve(list, "func_type_args")) {
+    if (!ParseTypeArguments(type_args_sexp, &func_type_args)) return false;
+  }
+
+  auto& delayed_type_args = TypeArguments::ZoneHandle(zone());
+  if (auto const type_args_sexp = Retrieve(list, "delayed_type_args")) {
+    if (!ParseTypeArguments(type_args_sexp, &delayed_type_args)) {
+      return false;
+    }
+  }
+
+  *out = Closure::New(inst_type_args, func_type_args, delayed_type_args,
+                      function, context, Heap::kOld);
+  return CanonicalizeInstance(list, out);
+}
+
+bool FlowGraphDeserializer::ParseField(SExpList* list, Object* out) {
+  auto const name_sexp = CheckSymbol(Retrieve(list, 1));
+  if (!ParseCanonicalName(name_sexp, out)) return false;
+  if (!out->IsField()) {
+    StoreError(list, "expected a Field name");
+    return false;
+  }
+  return true;
+}
+
+bool FlowGraphDeserializer::ParseFunction(SExpList* list, Object* out) {
+  ASSERT(out != nullptr);
+  if (list == nullptr) return false;
+
+  auto const name_sexp = CheckSymbol(Retrieve(list, 1));
+  if (!ParseCanonicalName(name_sexp, out)) return false;
+  if (!out->IsFunction()) {
+    StoreError(list, "expected a Function name");
+    return false;
+  }
+  auto& function = Function::Cast(*out);
+  // Check the kind expected by the S-expression if one was specified.
+  if (auto const kind_sexp = CheckSymbol(list->ExtraLookupValue("kind"))) {
+    RawFunction::Kind kind;
+    if (!RawFunction::ParseKind(kind_sexp->value(), &kind)) {
+      StoreError(kind_sexp, "unexpected function kind");
+      return false;
+    }
+    if (function.kind() != kind) {
+      auto const kind_str = RawFunction::KindToCString(function.kind());
+      StoreError(list, "retrieved function has kind %s", kind_str);
+      return false;
+    }
+  }
+  return true;
+}
+
+bool FlowGraphDeserializer::ParseImmutableList(SExpList* list, Object* out) {
+  ASSERT(out != nullptr);
+  if (list == nullptr) return false;
+
+  *out = Array::New(list->Length() - 1, Heap::kOld);
+  auto& arr = Array::Cast(*out);
+  // Arrays may contain other arrays, so we'll need a new handle in which to
+  // store elements.
+  auto& elem = Object::Handle(zone());
+  for (intptr_t i = 1; i < list->Length(); i++) {
+    if (!ParseDartValue(Retrieve(list, i), &elem)) return false;
+    arr.SetAt(i - 1, elem);
+  }
+  if (auto type_args_sexp = list->ExtraLookupValue("type_args")) {
+    if (!ParseTypeArguments(type_args_sexp, &array_type_args_)) return false;
+    arr.SetTypeArguments(array_type_args_);
+  }
+  arr.MakeImmutable();
+  return CanonicalizeInstance(list, out);
+}
+
+bool FlowGraphDeserializer::ParseInstance(SExpList* list, Object* out) {
+  ASSERT(out != nullptr);
+  if (list == nullptr) return false;
   auto const cid_sexp = CheckInteger(Retrieve(list, 1));
   if (cid_sexp == nullptr) return false;
 
@@ -1366,34 +1647,310 @@
 
   instance_class_ = table->At(cid_sexp->value());
   *out = Instance::New(instance_class_, Heap::kOld);
+  auto& instance = Instance::Cast(*out);
 
-  if (list->Length() > 2) {
-    auto const fields_sexp = CheckTaggedList(Retrieve(list, 2), "Fields");
-    if (fields_sexp == nullptr) return false;
-    auto it = fields_sexp->ExtraIterator();
-    while (auto kv = it.Next()) {
-      tmp_string_ = String::New(kv->key);
-      instance_field_ = instance_class_.LookupFieldAllowPrivate(
-          tmp_string_, /*instance_only=*/true);
-      if (instance_field_.IsNull()) {
-        StoreError(list, "cannot find field %s", kv->key);
-        return false;
-      }
-
-      if (auto const inst = CheckTaggedList(kv->value, "Instance")) {
-        // Unsure if this will be necessary, so for now not doing fresh
-        // Instance/Class handle allocations unless it is.
-        StoreError(inst, "nested instances not handled yet");
-        return false;
-      }
-      if (!ParseDartValue(kv->value, &instance_object_)) return false;
-      out->SetField(instance_field_, instance_object_);
+  if (auto const type_args = list->ExtraLookupValue("type_args")) {
+    instance_type_args_ = TypeArguments::null();
+    if (!ParseTypeArguments(type_args, &instance_type_args_)) return false;
+    if (!instance_class_.IsGeneric()) {
+      StoreError(list,
+                 "type arguments provided for an instance of a "
+                 "non-generic class");
+      return false;
     }
+    instance.SetTypeArguments(instance_type_args_);
   }
+
+  // Pick out and store the final instance fields of the class, as values must
+  // be provided for them. Error if there are any non-final instance fields.
+  instance_fields_array_ = instance_class_.fields();
+  auto const field_count = instance_fields_array_.Length();
+  GrowableArray<const Field*> final_fields(zone(), field_count);
+  for (intptr_t i = 0, n = field_count; i < n; i++) {
+    instance_field_ = Field::RawCast(instance_fields_array_.At(i));
+    if (!instance_field_.is_instance()) continue;
+    if (!instance_field_.is_final()) {
+      StoreError(list, "class for instance has non-final instance fields");
+      return false;
+    }
+    auto& fresh_handle = Field::Handle(zone(), instance_field_.raw());
+    final_fields.Add(&fresh_handle);
+  }
+
+  // If there is no (Fields...) sub-expression or it has no extra info, then
+  // ensure there are no final fields before returning the canonicalized form.
+  SExpList* fields_sexp = nullptr;
+  bool fields_provided = list->Length() > 2;
+  if (fields_provided) {
+    fields_sexp = CheckTaggedList(Retrieve(list, 2), "Fields");
+    if (fields_sexp == nullptr) return false;
+    fields_provided = fields_sexp->ExtraLength() != 0;
+  }
+  if (!fields_provided) {
+    if (!final_fields.is_empty()) {
+      StoreError(list, "values not provided for final fields of instance");
+      return false;
+    }
+    return CanonicalizeInstance(list, out);
+  }
+
+  // At this point, we have final instance field values to set on the new
+  // instance before canonicalization. When setting instance fields, we may
+  // cause field guards to be invalidated. Because of this, we must either be
+  // running on the mutator thread or be at a safepoint when calling `SetField`.
+  //
+  // For IR round-trips, the constants we create have already existed before in
+  // the VM heap, which means field invalidation cannot occur. Thus, we create a
+  // closure that sets the fields of the instance and then conditionally run
+  // that closure at a safepoint if not in the mutator thread.
+  //
+  // TODO(dartbug.com/36882): When deserializing IR that was not generated
+  // during the RoundTripSerialization pass, we are no longer guaranteed that
+  // deserialization of instances will not invalidate field guards. Thus, we may
+  // need to support invalidating field guards on non-mutator threads or fall
+  // back onto forcing the deserialization to happen on the mutator thread.
+  auto set_instance_fields = [&]() {
+    auto& inst = Instance::Cast(*out);
+    // We'll need to allocate a handle for the parsed value as we may have
+    // instances as field values and so this function may be re-entered.
+    auto& value = Object::Handle(zone());
+    for (auto field : final_fields) {
+      tmp_string_ = field->UserVisibleName();
+      auto const name = tmp_string_.ToCString();
+      auto const value_sexp = Retrieve(fields_sexp, name);
+      if (value_sexp == nullptr) {
+        StoreError(list, "no value provided for final instance field %s", name);
+        return false;
+      }
+      if (!ParseDartValue(value_sexp, &value)) return false;
+      inst.SetField(*field, value);
+    }
+    return true;
+  };
+
+  auto const t = Thread::Current();
+  if (!t->IsMutatorThread()) {
+    SafepointOperationScope safepoint_scope(t);
+    if (!set_instance_fields()) return false;
+  } else {
+    if (!set_instance_fields()) return false;
+  }
+
+  return CanonicalizeInstance(list, out);
+}
+
+bool FlowGraphDeserializer::ParseType(SExpression* sexp, Object* out) {
+  ASSERT(out != nullptr);
+  if (sexp == nullptr) return false;
+
+  if (auto const sym = sexp->AsSymbol()) {
+    auto const val = ParseValue(sexp, /*allow_pending=*/false);
+    if (val == nullptr) {
+      StoreError(sexp, "expected type or reference to constant definition");
+      return false;
+    }
+    if (!val->BindsToConstant()) {
+      StoreError(sexp, "reference to non-constant definition");
+      return false;
+    }
+    *out = val->BoundConstant().raw();
+    if (!out->IsType()) {
+      StoreError(sexp, "expected Type constant");
+      return false;
+    }
+    return true;
+  }
+  auto const list = CheckTaggedList(sexp, "Type");
+  if (list == nullptr) return false;
+
+  const auto hash_sexp = CheckInteger(list->ExtraLookupValue("hash"));
+  const auto is_recursive = hash_sexp != nullptr;
+  // 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;
+  if (is_recursive) {
+    if (pending_typeref_map_.LookupValue(old_hash) != nullptr) {
+      StoreError(sexp, "already parsing a type with hash %" Pd64 "",
+                 hash_sexp->value());
+      return false;
+    }
+    pending_typerefs = new (zone()) ZoneGrowableArray<TypeRef*>(zone(), 2);
+    pending_typeref_map_.Insert(old_hash, pending_typerefs);
+  }
+
+  const auto cls_sexp = CheckTaggedList(Retrieve(list, 1), "Class");
+  if (cls_sexp == nullptr) {
+    // TODO(sstrickl): Handle types not derived from classes.
+    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 = Type::Cast(*out);
+  if (auto const sig_sexp = list->ExtraLookupValue("signature")) {
+    auto& function = Function::Handle(zone());
+    if (!ParseDartValue(sig_sexp, &function)) return false;
+    type.set_signature(function);
+  }
+  if (is_recursive) {
+    while (!pending_typerefs->is_empty()) {
+      auto const ref = pending_typerefs->RemoveLast();
+      ASSERT(ref != nullptr);
+      ref->set_type(type);
+    }
+    pending_typeref_map_.Remove(old_hash);
+
+    // If there are still pending typerefs, we can't canonicalize yet until
+    // an enclosing type where we have resolved them. This is a conservative
+    // check, as we do not ensure that any of the still-pending typerefs are
+    // found within this type.
+    //
+    // This is within the is_recursive check because if this type was
+    // non-recursive, then even if there are pending type refs, we are
+    // guaranteed that none of them are in this type.
+    if (ArePendingTypeRefs()) return true;
+  }
+
+  // Need to set this for canonicalization. We ensure in the serializer
+  // that only finalized types are successfully serialized.
+  type.SetIsFinalized();
+  return CanonicalizeInstance(list, out);
+}
+
+bool FlowGraphDeserializer::ParseTypeArguments(SExpression* sexp, Object* out) {
+  ASSERT(out != nullptr);
+  if (sexp == nullptr) return false;
+
+  if (auto const sym = sexp->AsSymbol()) {
+    auto const val = ParseValue(sexp, /*allow_pending=*/false);
+    if (val == nullptr) {
+      StoreError(sexp,
+                 "expected type arguments or reference to constant definition");
+      return false;
+    }
+    if (!val->BindsToConstant()) {
+      StoreError(sexp, "reference to non-constant definition");
+      return false;
+    }
+    *out = val->BoundConstant().raw();
+    if (!out->IsTypeArguments()) {
+      StoreError(sexp, "expected TypeArguments constant");
+      return false;
+    }
+    return true;
+  }
+  auto const list = CheckTaggedList(sexp, "TypeArguments");
+  if (list == nullptr) return false;
+
+  *out = TypeArguments::New(list->Length() - 1, Heap::kOld);
+  auto& type_args = TypeArguments::Cast(*out);
+  // We may reenter ParseTypeArguments while parsing one of the elements, so we
+  // need a fresh handle here.
+  auto& elem = AbstractType::Handle(zone());
+  for (intptr_t i = 1, n = list->Length(); i < n; i++) {
+    if (!ParseAbstractType(Retrieve(list, i), &elem)) return false;
+    type_args.SetTypeAt(i - 1, elem);
+  }
+
+  // If there are still pending typerefs, we can't canonicalize yet.
+  if (ArePendingTypeRefs()) return true;
+
+  return CanonicalizeInstance(list, out);
+}
+
+bool FlowGraphDeserializer::ParseTypeParameter(SExpList* list, Object* out) {
+  ASSERT(out != nullptr);
+  if (list == nullptr) return false;
+
+  const Function* function = nullptr;
+  const Class* cls = nullptr;
+  if (auto const func_sexp = CheckSymbol(list->ExtraLookupValue("function"))) {
+    if (!ParseCanonicalName(func_sexp, &type_param_function_)) return false;
+    if (!type_param_function_.IsFunction() || type_param_function_.IsNull()) {
+      StoreError(func_sexp, "not a function name");
+      return false;
+    }
+    function = &type_param_function_;
+  } else if (auto const class_sexp =
+                 CheckInteger(list->ExtraLookupValue("class"))) {
+    const intptr_t cid = class_sexp->value();
+    auto const table = thread()->isolate()->class_table();
+    if (!table->HasValidClassAt(cid)) {
+      StoreError(class_sexp, "not a valid class id");
+      return false;
+    }
+    type_param_class_ = table->At(cid);
+    cls = &type_param_class_;
+  } else {
+    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());
+
+  if (function != nullptr) {
+    *out = function->LookupTypeParameter(tmp_string_, nullptr);
+  }
+  if (cls != nullptr && out->IsNull()) {
+    *out = cls->LookupTypeParameter(tmp_string_);
+  }
+  if (out->IsNull()) {
+    StoreError(name_sexp, "no type parameter found for name");
+    return false;
+  }
+  return CanonicalizeInstance(list, out);
+}
+
+bool FlowGraphDeserializer::ParseTypeRef(SExpList* list, Object* out) {
+  ASSERT(out != nullptr);
+  if (list == nullptr) return false;
+
+  const bool contains_type = list->Length() > 1;
+  if (contains_type) {
+    auto& type = Type::Handle(zone());
+    if (!ParseAbstractType(Retrieve(list, 1), &type)) return false;
+    *out = TypeRef::New(type);
+    // If the TypeRef appears outside the referrent, then the referrent
+    // should be already canonicalized. This serves as a double-check that
+    // is the case.
+    return CanonicalizeInstance(list, out);
+  }
+  // If there is no type in the body, then this must be a referrent to
+  // a Type containing this TypeRef. That means we must have a hash value.
+  auto const hash_sexp = CheckInteger(Retrieve(list, "hash"));
+  if (hash_sexp == nullptr) return false;
+  auto const old_hash = hash_sexp->value();
+  auto const pending = pending_typeref_map_.LookupValue(old_hash);
+  if (pending == nullptr) {
+    StoreError(list, "reference to recursive type found outside type");
+    return false;
+  }
+  *out = TypeRef::New(Object::null_abstract_type());
+  pending->Add(static_cast<TypeRef*>(out));
+
+  // We can only canonicalize TypeRefs appearing within their referrent
+  // when its containing value is canonicalized.
   return true;
 }
 
 bool FlowGraphDeserializer::ParseCanonicalName(SExpSymbol* sym, Object* obj) {
+  ASSERT(obj != nullptr);
   if (sym == nullptr) return false;
   auto const name = sym->value();
   // TODO(sstrickl): No library URL, handle this better.
@@ -1496,7 +2053,8 @@
       ASSERT(!tmp_string_.IsNull());
       auto const parent_name = tmp_string_.ToCString();
       // ImplicitClosureFunctions (tearoffs) have the same name as the Function
-      // to which they are attached. We won't handle any further nesting.
+      // to which they are attached. We currently don't handle any other kinds
+      // of local functions.
       if (name_function_.HasImplicitClosureFunction() && *func_end == '\0' &&
           strncmp(parent_name, func_start, name_len) == 0) {
         *obj = name_function_.ImplicitClosureFunction();
@@ -1506,6 +2064,16 @@
       return false;
     }
 
+    // Check for the prefix "<anonymous ..." in the name and fail if found,
+    // since we can't resolve these.
+    static auto const anon_prefix = "<anonymous ";
+    static const intptr_t prefix_len = strlen(anon_prefix);
+    if ((name_len > prefix_len) &&
+        strncmp(anon_prefix, func_start, prefix_len) == 0) {
+      StoreError(sym, "cannot resolve anonymous values");
+      return false;
+    }
+
     tmp_string_ = String::FromUTF8(reinterpret_cast<const uint8_t*>(func_start),
                                    name_len);
     name_function_ = name_class_.LookupFunctionAllowPrivate(tmp_string_);
@@ -1533,7 +2101,7 @@
 }
 
 // Following the lead of BaseFlowGraphBuilder::MayCloneField here.
-const Field& FlowGraphDeserializer::MayCloneField(const Field& field) {
+const Field& FlowGraphDeserializer::MayCloneField(const Field& field) const {
   if ((Compiler::IsBackgroundCompilation() ||
        FLAG_force_clone_compiler_objects) &&
       field.IsOriginal()) {
@@ -1552,7 +2120,7 @@
   const auto kind_sexp = CheckSymbol(Retrieve(list, "kind"));
   if (kind_sexp == nullptr) return false;
   Slot::Kind kind;
-  if (!Slot::KindFromCString(kind_sexp->value(), &kind)) {
+  if (!Slot::ParseKind(kind_sexp->value(), &kind)) {
     StoreError(kind_sexp, "unknown Slot kind");
     return false;
   }
@@ -1562,6 +2130,7 @@
       auto& field = Field::ZoneHandle(zone());
       const auto field_sexp = CheckTaggedList(Retrieve(list, "field"), "Field");
       if (!ParseDartValue(field_sexp, &field)) return false;
+      ASSERT(parsed_function_ != nullptr);
       *out = &Slot::Get(MayCloneField(field), parsed_function_);
       break;
     }
@@ -1610,31 +2179,151 @@
   return true;
 }
 
-Value* FlowGraphDeserializer::AddNewPendingValue(intptr_t index) {
-  ASSERT(flow_graph_ != nullptr);
-  auto const val = new (zone()) Value(flow_graph_->constant_null());
-  AddPendingValue(index, val);
-  return val;
-}
-
-void FlowGraphDeserializer::AddPendingValue(intptr_t index, Value* val) {
-  ASSERT(!definition_map_.HasKey(index));
-  auto value_list = values_map_.LookupValue(index);
-  if (value_list == nullptr) {
-    value_list = new (zone()) ZoneGrowableArray<Value*>(zone(), 2);
-    values_map_.Insert(index, value_list);
+bool FlowGraphDeserializer::ArePendingTypeRefs() const {
+  // We'll do a deep check, because while there may be recursive types still
+  // being parsed, if there are no pending type refs to those recursive types,
+  // we're still good to canonicalize.
+  if (pending_typeref_map_.IsEmpty()) return false;
+  auto it = pending_typeref_map_.GetIterator();
+  while (auto kv = it.Next()) {
+    if (!kv->value->is_empty()) return true;
   }
-  value_list->Add(val);
+  return false;
 }
 
-void FlowGraphDeserializer::FixPendingValues(intptr_t index, Definition* def) {
+bool FlowGraphDeserializer::CreateICData(SExpList* list, Instruction* inst) {
+  ASSERT(inst != nullptr);
+  if (list == nullptr) return false;
+
+  const String* function_name = nullptr;
+  Array& arguments_descriptor = Array::Handle(zone());
+  intptr_t num_args_checked;
+  ICData::RebindRule rebind_rule;
+
+  if (auto const call = inst->AsInstanceCall()) {
+    function_name = &call->function_name();
+    arguments_descriptor = call->GetArgumentsDescriptor();
+    num_args_checked = call->checked_argument_count();
+    rebind_rule = ICData::RebindRule::kInstance;
+  } else if (auto const call = inst->AsStaticCall()) {
+    function_name = &String::Handle(zone(), call->function().name());
+    arguments_descriptor = call->GetArgumentsDescriptor();
+    num_args_checked =
+        MethodRecognizer::NumArgsCheckedForStaticCall(call->function());
+    rebind_rule = ICData::RebindRule::kStatic;
+  } else {
+    StoreError(list, "unexpected instruction type for ICData");
+    return false;
+  }
+
+  auto type_ptr = &Object::null_abstract_type();
+  if (auto const type_sexp = list->ExtraLookupValue("receivers_static_type")) {
+    auto& type = AbstractType::ZoneHandle(zone());
+    if (!ParseAbstractType(type_sexp, &type)) return false;
+    type_ptr = &type;
+  }
+
+  ASSERT(parsed_function_ != nullptr);
+  const auto& ic_data = ICData::ZoneHandle(
+      zone(), ICData::New(parsed_function_->function(), *function_name,
+                          arguments_descriptor, inst->deopt_id(),
+                          num_args_checked, rebind_rule, *type_ptr));
+
+  if (auto const is_mega_sexp =
+          CheckBool(list->ExtraLookupValue("is_megamorphic"))) {
+    ic_data.set_is_megamorphic(is_mega_sexp->value());
+  }
+
+  auto const class_table = thread()->isolate()->class_table();
+  GrowableArray<intptr_t> class_ids(zone(), 2);
+  for (intptr_t i = 1, n = list->Length(); i < n; i++) {
+    auto const entry = CheckList(Retrieve(list, i));
+    if (entry == nullptr) return false;
+    ASSERT(ic_data.NumArgsTested() == entry->Length());
+
+    intptr_t count = 0;
+    if (auto const count_sexp =
+            CheckInteger(entry->ExtraLookupValue("count"))) {
+      count = count_sexp->value();
+    }
+
+    auto& target = Function::ZoneHandle(zone());
+    if (!ParseDartValue(Retrieve(entry, "target"), &target)) return false;
+
+    // We can't use AddCheck for NumArgsTested < 2. We'll handle 0 here, and
+    // 1 after the for loop.
+    if (entry->Length() == 0) {
+      if (count != 0) {
+        StoreError(entry, "expected a zero count for no checked args");
+        return false;
+      }
+      ic_data.AddTarget(target);
+      continue;
+    }
+
+    class_ids.Clear();
+    for (intptr_t j = 0, num_cids = entry->Length(); j < num_cids; j++) {
+      auto const cid_sexp = CheckInteger(Retrieve(entry, j));
+      if (cid_sexp == nullptr) return false;
+      const intptr_t cid = cid_sexp->value();
+      // kObjectCid is a special case used for AddTarget() entries with
+      // a non-zero number of checked arguments.
+      if (cid != kObjectCid && !class_table->HasValidClassAt(cid)) {
+        StoreError(cid_sexp, "cid is not a valid class");
+        return false;
+      }
+      class_ids.Add(cid);
+    }
+
+    if (entry->Length() == 1) {
+      ic_data.AddReceiverCheck(class_ids.At(0), target, count);
+    } else {
+      ic_data.AddCheck(class_ids, target, count);
+    }
+  }
+
+  if (auto const call = inst->AsInstanceCall()) {
+    call->set_ic_data(&ic_data);
+  } else if (auto const call = inst->AsStaticCall()) {
+    call->set_ic_data(&ic_data);
+  }
+
+  return true;
+}
+
+Value* FlowGraphDeserializer::AddNewPendingValue(SExpression* sexp,
+                                                 intptr_t index,
+                                                 bool inherit_type) {
+  ASSERT(flow_graph_ != nullptr);
+  auto const value = new (zone()) Value(flow_graph_->constant_null());
+  ASSERT(!definition_map_.HasKey(index));
+  auto list = values_map_.LookupValue(index);
+  if (list == nullptr) {
+    list = new (zone()) ZoneGrowableArray<PendingValue>(zone(), 2);
+    values_map_.Insert(index, list);
+  }
+  list->Add({sexp, value, inherit_type});
+  return value;
+}
+
+bool FlowGraphDeserializer::FixPendingValues(intptr_t index, Definition* def) {
   if (auto value_list = values_map_.LookupValue(index)) {
     for (intptr_t i = 0; i < value_list->length(); i++) {
-      auto const val = value_list->At(i);
-      val->BindTo(def);
+      const auto& value_info = value_list->At(i);
+      auto const value = value_info.value;
+      const bool inherit_type = value_info.inherit_type;
+      value->BindTo(def);
+      if (!inherit_type) continue;
+      if (def->HasType()) {
+        value->reaching_type_ = def->Type();
+      } else {
+        StoreError(value_info.sexp, "value inherits type, but no type found");
+        return false;
+      }
     }
     values_map_.Remove(index);
   }
+  return true;
 }
 
 PushArgumentsArray* FlowGraphDeserializer::FetchPushedArguments(SExpList* list,
@@ -1721,7 +2410,7 @@
 bool FlowGraphDeserializer::IsTag(SExpression* sexp, const char* label) {
   auto const sym = CheckSymbol(sexp);
   if (sym == nullptr) return false;
-  if (label != nullptr && strcmp(label, sym->value()) != 0) {
+  if (label != nullptr && !sym->Equals(label)) {
     StoreError(sym, "expected symbol %s", label);
     return false;
   }
diff --git a/runtime/vm/compiler/backend/il_deserializer.h b/runtime/vm/compiler/backend/il_deserializer.h
index 2ebb507..2b0040a 100644
--- a/runtime/vm/compiler/backend/il_deserializer.h
+++ b/runtime/vm/compiler/backend/il_deserializer.h
@@ -47,21 +47,23 @@
         zone_(ASSERT_NOTNULL(zone)),
         root_sexp_(ASSERT_NOTNULL(root)),
         parsed_function_(pf),
-        block_map_(zone_),
-        pushed_stack_map_(zone_),
-        definition_map_(zone_),
-        values_map_(zone_),
+        block_map_(zone),
+        pushed_stack_map_(zone),
+        definition_map_(zone),
+        values_map_(zone),
+        recursive_types_map_(zone),
+        pending_typeref_map_(zone),
+        array_type_args_(TypeArguments::Handle(zone)),
         instance_class_(Class::Handle(zone)),
         instance_field_(Field::Handle(zone)),
-        instance_object_(Object::Handle(zone)),
+        instance_fields_array_(Array::Handle(zone)),
+        instance_type_args_(TypeArguments::Handle(zone)),
         name_class_(Class::Handle(zone)),
         name_field_(Field::Handle(zone)),
         name_function_(Function::Handle(zone)),
         name_library_(Library::Handle(zone)),
-        value_class_(Class::Handle(zone)),
-        value_object_(Object::Handle(zone)),
-        value_type_(AbstractType::Handle(zone)),
-        value_type_args_(TypeArguments::Handle(zone)),
+        type_param_class_(Class::Handle(zone)),
+        type_param_function_(Function::Handle(zone)),
         tmp_string_(String::Handle(zone)) {
     // See canonicalization comment in ParseDartValue as to why this is
     // currently necessary.
@@ -86,20 +88,27 @@
 
 #define FOR_EACH_HANDLED_INSTRUCTION_IN_DESERIALIZER(M)                        \
   M(AllocateObject)                                                            \
+  M(AssertAssignable)                                                          \
+  M(AssertBoolean)                                                             \
+  M(BooleanNegate)                                                             \
   M(Branch)                                                                    \
   M(CheckNull)                                                                 \
   M(CheckStackOverflow)                                                        \
   M(Constant)                                                                  \
   M(DebugStepCheck)                                                            \
   M(Goto)                                                                      \
+  M(InstanceCall)                                                              \
+  M(LoadClassId)                                                               \
   M(LoadField)                                                                 \
+  M(NativeCall)                                                                \
   M(Parameter)                                                                 \
   M(PushArgument)                                                              \
   M(Return)                                                                    \
   M(SpecialParameter)                                                          \
   M(StaticCall)                                                                \
   M(StoreInstanceField)                                                        \
-  M(StrictCompare)
+  M(StrictCompare)                                                             \
+  M(Throw)
 
   // Helper methods for AllUnhandledInstructions.
   static bool IsHandledInstruction(Instruction* inst);
@@ -214,6 +223,22 @@
 
 #undef HANDLER_DECL
 
+  // Common information parsed from call instruction S-expressions.
+  struct CallInfo : public ValueObject {
+    explicit CallInfo(Zone* zone) : argument_names(Array::ZoneHandle(zone)) {}
+
+    Array& argument_names;
+    intptr_t type_args_len = 0;
+    intptr_t args_len = 0;
+    PushArgumentsArray* arguments = nullptr;
+    CompileType* result_type = nullptr;
+    Code::EntryKind entry_kind = Code::EntryKind::kNormal;
+  };
+
+  // Helper function for parsing call instructions that returns a structure
+  // of information common to all calls.
+  bool ParseCallInfo(SExpList* call, CallInfo* out);
+
   // Parses [sexp] as a value form, that is, either the binding name for
   // a definition as a symbol or the form (value <name> { ... }).
   // If [allow_pending], then values for definitions not already in the
@@ -235,14 +260,34 @@
   // Parses a Dart value and returns a canonicalized result.
   bool ParseDartValue(SExpression* sexp, Object* out);
 
-  // Helper function for ParseDartValue for parsing instances.
-  // Does not canonicalize (that is currently done in ParseDartValue), so
-  // do not call this method directly.
-  bool ParseInstance(SExpList* list, Instance* out);
+  // Canonicalizes and replaces the original contents of the handle pointed to
+  // by [inst] if [inst] is an Instance (if not, it trivially succeeds). The
+  // replacement happens whether successful or not. [sexp] is the SExpression
+  // to be used for error reporting.
+  bool CanonicalizeInstance(SExpression* sexp, Object* inst);
+
+  // Helper functions for ParseDartValue for parsing particular type of values.
+  // If necessary, they canonicalize the returned value, and so may be used
+  // directly by other code as well. Helpers that take SExpression* take either
+  // serialized constants or references to constant definitions.
+  //
+  // Due to particulars of operator=() on non-Object values, for a given X,
+  // ParseX takes Object* instead of X* for the out parameter.
+  bool ParseAbstractType(SExpression* sexp, Object* out);
+  bool ParseClass(SExpList* list, Object* out);
+  bool ParseClosure(SExpList* list, Object* out);
+  bool ParseField(SExpList* list, Object* out);
+  bool ParseFunction(SExpList* list, Object* out);
+  bool ParseImmutableList(SExpList* list, Object* out);
+  bool ParseInstance(SExpList* list, Object* out);
+  bool ParseType(SExpression* sexp, Object* out);
+  bool ParseTypeParameter(SExpList* list, Object* out);
+  bool ParseTypeArguments(SExpression* sexp, Object* out);
+  bool ParseTypeRef(SExpList* list, Object* out);
 
   bool ParseCanonicalName(SExpSymbol* sym, Object* out);
 
-  const Field& MayCloneField(const Field& field);
+  const Field& MayCloneField(const Field& field) const;
   bool ParseSlot(SExpList* list, const Slot** out);
 
   bool ParseBlockId(SExpSymbol* sym, intptr_t* out);
@@ -250,16 +295,21 @@
   bool ParseUse(SExpSymbol* sym, intptr_t* out);
   bool ParseSymbolAsPrefixedInt(SExpSymbol* sym, char prefix, intptr_t* out);
 
+  bool ArePendingTypeRefs() const;
+
+  // Allocates a new ICData structure. [list] is the ICData S-expression, while
+  // [inst] is the Instruction generated from the instruction S-expression
+  // containing [list].
+  bool CreateICData(SExpList* list, Instruction* inst);
+
   // Helper function for creating a placeholder value when the definition
-  // has not yet been seen.
-  Value* AddNewPendingValue(intptr_t index);
+  // with index [i] has not yet been seen. If [inherit_type], then the type of
+  // the definition should be used as the reaching type for the use. [s] is used
+  // for any errors that occur when resolving the pending value.
+  Value* AddNewPendingValue(SExpression* s, intptr_t i, bool inherit_type);
 
-  // Similar helper, but where we already have a created value.
-  void AddPendingValue(intptr_t index, Value* val);
-
-  // Helper function for rebinding pending values once the definition has
-  // been located.
-  void FixPendingValues(intptr_t index, Definition* def);
+  // Helper function for rebinding values pending on this definition.
+  bool FixPendingValues(intptr_t index, Definition* def);
 
   // Creates a PushArgumentsArray of size [len] from [pushed_stack_] if there
   // are enough and pops the fetched arguments from the stack.
@@ -326,24 +376,46 @@
   // Map from variable indexes to definitions.
   IntMap<Definition*> definition_map_;
 
+  // Information needed to handle uses seen prior to their definitions.
+  struct PendingValue {
+    // SExpression used for error reporting.
+    SExpression* sexp;
+    // Value to be rebound once the right definition is found.
+    Value* value;
+    // Whether the type should inherit the type of the found definition.
+    bool inherit_type;
+  };
+
   // Map from variable indices to lists of values. The list of values are
   // values that were parsed prior to the corresponding definition being found.
-  IntMap<ZoneGrowableArray<Value*>*> values_map_;
+  IntMap<ZoneGrowableArray<PendingValue>*> values_map_;
+
+  // Map from hash values to SExpLists. This is used by ParseTypeRef to
+  // determine whether or not the recursive type it refers to is being currently
+  // built. The SExpList can be used to report hash collisions.
+  IntMap<SExpList*> recursive_types_map_;
+
+  // Map from hash values to arrays of TypeRefs. This is used by ParseType and
+  // ParseTypeRef to store and later fill in TypeRefs pending on the type being
+  // constructed. Since entries are added at the start of parsing recursive
+  // Type S-exps and removed before the resulting Type is successfully returned,
+  // this map should be empty outside of parsing recursive types.
+  IntMap<ZoneGrowableArray<TypeRef*>*> pending_typeref_map_;
 
   // Temporary handles used by functions that are not re-entrant or where the
   // handle is not live after the re-entrant call. Comments show which handles
   // are expected to only be used within a single method.
-  Class& instance_class_;           // ParseInstance
-  Field& instance_field_;           // ParseInstance
-  Object& instance_object_;         // ParseInstance
-  Class& name_class_;               // ParseCanonicalName
-  Field& name_field_;               // ParseCanonicalName
-  Function& name_function_;         // ParseCanonicalName
-  Library& name_library_;           // ParseCanonicalName
-  Class& value_class_;              // ParseDartValue
-  Object& value_object_;            // ParseDartValue
-  AbstractType& value_type_;        // ParseDartValue
-  TypeArguments& value_type_args_;  // ParseDartValue
+  TypeArguments& array_type_args_;     // ParseImmutableList
+  Class& instance_class_;              // ParseInstance
+  Field& instance_field_;              // ParseInstance
+  Array& instance_fields_array_;       // ParseInstance
+  TypeArguments& instance_type_args_;  // ParseInstance
+  Class& name_class_;                  // ParseCanonicalName
+  Field& name_field_;                  // ParseCanonicalName
+  Function& name_function_;            // ParseCanonicalName
+  Library& name_library_;              // ParseCanonicalName
+  Class& type_param_class_;            // ParseTypeParameter
+  Function& type_param_function_;      // ParseTypeParameter
   // Uses of string handles tend to be immediate, so we only need one.
   String& tmp_string_;
 
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 72bc6b3..a290225 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -392,7 +392,9 @@
   compiler->GenerateRuntimeCall(token_pos, deopt_id,
                                 kNonBoolTypeErrorRuntimeEntry, 1, locs);
   // We should never return here.
+#if defined(DEBUG)
   __ int3();
+#endif
   __ Bind(&done);
 }
 
@@ -2761,10 +2763,9 @@
 
 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   __ Bind(compiler->GetJumpLabel(this));
-  compiler->AddExceptionHandler(catch_try_index(), try_index(),
-                                compiler->assembler()->CodeSize(),
-                                handler_token_pos(), is_generated(),
-                                catch_handler_types_, needs_stacktrace());
+  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());
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index 0dd6d6b..c8166bc 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -345,9 +345,7 @@
     range_->PrintTo(f);
   }
 
-  if (type_ != NULL &&
-      ((type_->ToNullableCid() != kDynamicCid) ||
-       !type_->ToAbstractType()->IsDynamicType() || !type_->is_nullable())) {
+  if (type_ != NULL) {
     f->Print(" ");
     type_->PrintTo(f);
   }
@@ -676,6 +674,11 @@
   f->Print(" . %s%s", slot().Name(), slot().is_immutable() ? " {final}" : "");
 }
 
+void LoadUntaggedInstr::PrintOperandsTo(BufferFormatter* f) const {
+  object()->PrintTo(f);
+  f->Print(", %" Pd, offset());
+}
+
 void InstantiateTypeInstr::PrintOperandsTo(BufferFormatter* f) const {
   const String& type_name = String::Handle(type().Name());
   f->Print("%s,", type_name.ToCString());
diff --git a/runtime/vm/compiler/backend/il_serializer.cc b/runtime/vm/compiler/backend/il_serializer.cc
index 5369159..1ab17fd 100644
--- a/runtime/vm/compiler/backend/il_serializer.cc
+++ b/runtime/vm/compiler/backend/il_serializer.cc
@@ -268,6 +268,9 @@
   AddSymbol(sexp, "FlowGraph");
   sexp->Add(CanonicalNameToSExp(flow_graph()->function()));
   AddExtraInteger(sexp, "deopt_id", start->deopt_id());
+  if (start->env() != nullptr) {
+    sexp->AddExtra("env", start->env()->ToSExpression(this));
+  }
   if (start->IsCompiledForOsr()) {
     AddExtraInteger(sexp, "osr_id", start->osr_id());
   }
@@ -325,8 +328,7 @@
 static bool ShouldSerializeType(CompileType* type) {
   return (FLAG_verbose_flow_graph_serialization ||
           FLAG_serialize_flow_graph_types) &&
-         type != NULL &&
-         (type->ToNullableCid() != kDynamicCid || !type->is_nullable());
+         type != nullptr;
 }
 
 SExpression* FlowGraphSerializer::FieldToSExp(const Field& field) {
@@ -343,19 +345,55 @@
 
 SExpression* FlowGraphSerializer::AbstractTypeToSExp(const AbstractType& t) {
   if (t.IsNull()) return nullptr;
+  ASSERT(t.IsFinalized());
   auto sexp = new (zone()) SExpList(zone());
   if (t.IsTypeParameter()) {
     const auto& param = TypeParameter::Cast(t);
     AddSymbol(sexp, "TypeParameter");
     tmp_string_ = param.name();
     AddSymbol(sexp, tmp_string_.ToCString());
+    if (param.IsFunctionTypeParameter()) {
+      if (param.parameterized_function() != flow_graph_->function().raw()) {
+        type_function_ = param.parameterized_function();
+        sexp->AddExtra("function", CanonicalNameToSExp(type_function_));
+      } else if (FLAG_verbose_flow_graph_serialization) {
+        sexp->AddExtra("function",
+                       CanonicalNameToSExp(flow_graph_->function()));
+      }
+    } else if (param.IsClassTypeParameter()) {
+      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());
+      }
+    }
     return sexp;
   }
   if (t.IsTypeRef()) {
     const auto& ref = TypeRef::Cast(t);
     AddSymbol(sexp, "TypeRef");
     type_ref_type_ = ref.type();
-    AddExtraInteger(sexp, "hash", type_ref_type_.Hash());
+    auto const hash = type_ref_type_.Hash();
+    // Check to see if this is a TypeRef to a type we're currently serializing.
+    // If it is not, then we need to serialize the underlying type, as it
+    // otherwise won't be available when deserializing.
+    auto const open_type = open_recursive_types_.LookupValue(hash);
+    if (open_type == nullptr) {
+      // Allocate a new handle as we may re-enter the TypeRef branch.
+      auto& type = AbstractType::Handle(zone(), ref.type());
+      sexp->Add(AbstractTypeToSExp(type));
+      // If we serialized the referrent, then we don't need this information,
+      // but it may be useful for debugging so add it in verbose mode.
+      if (FLAG_verbose_flow_graph_serialization) {
+        AddExtraInteger(sexp, "hash", hash);
+      }
+    } else {
+      // Make sure we didn't have a hash collision.
+      ASSERT(open_type->Equals(type_ref_type_));
+      AddExtraInteger(sexp, "hash", hash);
+    }
     if (FLAG_verbose_flow_graph_serialization) {
       AddExtraString(sexp, "type", type_ref_type_.ToCString());
     }
@@ -363,28 +401,43 @@
   }
   ASSERT(t.IsType());
   AddSymbol(sexp, "Type");
-  const auto& typ = Type::Cast(t);
-  ASSERT(typ.IsFinalized());
-  if (typ.HasTypeClass()) {
-    type_class_ = typ.type_class();
+  const auto& type = Type::Cast(t);
+  if (!type.token_pos().IsNoSource()) {
+    AddExtraInteger(sexp, "token_pos", type.token_pos().value());
+  }
+  // We want to check for the type being recursive before we may serialize
+  // any sub-parts that include possible TypeRefs to this type.
+  const bool is_recursive = type.IsRecursive();
+  intptr_t hash = 0;
+  if (is_recursive) {
+    hash = type.Hash();
+    AddExtraInteger(sexp, "hash", hash);
+    open_recursive_types_.Insert(hash, &type);
+  }
+  if (type.HasTypeClass()) {
+    type_class_ = type.type_class();
     // This avoids re-entry as long as serializing a class doesn't involve
     // serializing concrete (non-parameter, non-reference) types.
     sexp->Add(DartValueToSExp(type_class_));
-    if (typ.IsRecursive()) {
-      AddExtraInteger(sexp, "hash", typ.Hash());
-    }
-    // Since type arguments may themselves be instantiations of generic
-    // classes, we may call back into this function in the middle of printing
-    // the TypeArguments and so we must allocate a fresh handle here.
-    const auto& args = TypeArguments::Handle(zone(), typ.arguments());
-    if (auto const args_sexp = NonEmptyTypeArgumentsToSExp(args)) {
-      sexp->AddExtra("type_args", args_sexp);
-    }
   } else {
     // TODO(dartbug.com/36882): Actually structure non-class types instead of
     // just printing out this version.
-    AddString(sexp, typ.ToCString());
+    AddExtraString(sexp, "name", type.ToCString());
   }
+  if (type.IsFunctionType()) {
+    type_function_ = type.signature();
+    sexp->AddExtra("signature", DartValueToSExp(type_function_));
+  }
+  // Since type arguments may themselves be instantiations of generic
+  // types, we may call back into this function in the middle of printing
+  // the TypeArguments and so we must allocate a fresh handle here.
+  const auto& args = TypeArguments::Handle(zone(), type.arguments());
+  if (auto const args_sexp = NonEmptyTypeArgumentsToSExp(args)) {
+    sexp->AddExtra("type_args", args_sexp);
+  }
+  // If we were parsing a recursive type, we're now done building it, so
+  // remove it from the open recursive types.
+  if (is_recursive) open_recursive_types_.Remove(hash);
   return sexp;
 }
 
@@ -422,6 +475,9 @@
     type_arguments_elem_ = ta.TypeAt(i);
     sexp->Add(DartValueToSExp(type_arguments_elem_));
   }
+  if (FLAG_verbose_flow_graph_serialization && ta.IsRecursive()) {
+    AddExtraInteger(sexp, "hash", ta.Hash());
+  }
   return sexp;
 }
 
@@ -634,15 +690,19 @@
   AddSymbol(constant_list, "Constants");
   for (intptr_t i = 0; i < initial_defs->length(); i++) {
     ASSERT(initial_defs->At(i)->IsConstant());
-    ConstantInstr* value = initial_defs->At(i)->AsConstant();
+    auto const definition = initial_defs->At(i)->AsDefinition();
     auto elem = new (zone()) SExpList(zone());
     AddSymbol(elem, "def");
-    elem->Add(UseToSExp(value->AsDefinition()));
+    elem->Add(UseToSExp(definition));
     // Use ObjectToSExp here, not DartValueToSExp!
-    elem->Add(ObjectToSExp(value->value()));
-    if (ShouldSerializeType(value->AsDefinition()->Type())) {
-      auto const val = value->AsDefinition()->Type()->ToSExpression(this);
-      elem->AddExtra("type", val);
+    elem->Add(ObjectToSExp(definition->AsConstant()->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));
+      }
     }
     constant_list->Add(elem);
   }
@@ -721,6 +781,9 @@
   if (env() != nullptr) {
     sexp->AddExtra("env", env()->ToSExpression(s));
   }
+  if (!token_pos().IsNoSource()) {
+    s->AddExtraInteger(sexp, "token_pos", token_pos().value());
+  }
 }
 
 SExpression* Definition::ToSExpression(FlowGraphSerializer* s) const {
@@ -737,6 +800,14 @@
   return sexp;
 }
 
+void AssertAssignableInstr::AddExtraInfoToSExpression(
+    SExpList* sexp,
+    FlowGraphSerializer* s) const {
+  Instruction::AddExtraInfoToSExpression(sexp, s);
+  sexp->AddExtra("type", s->DartValueToSExp(dst_type()));
+  sexp->AddExtra("name", s->DartValueToSExp(dst_name()));
+}
+
 void ConstantInstr::AddOperandsToSExpression(SExpList* sexp,
                                              FlowGraphSerializer* s) const {
   sexp->Add(s->DartValueToSExp(value()));
@@ -811,6 +882,7 @@
 void StoreInstanceFieldInstr::AddExtraInfoToSExpression(
     SExpList* sexp,
     FlowGraphSerializer* s) const {
+  Instruction::AddExtraInfoToSExpression(sexp, s);
   if (is_initialization_ || FLAG_verbose_flow_graph_serialization) {
     s->AddExtraBool(sexp, "is_init", is_initialization_);
   }
@@ -882,6 +954,7 @@
 void DebugStepCheckInstr::AddExtraInfoToSExpression(
     SExpList* sexp,
     FlowGraphSerializer* s) const {
+  Instruction::AddExtraInfoToSExpression(sexp, s);
   if (stub_kind_ != RawPcDescriptors::kAnyKind ||
       FLAG_verbose_flow_graph_serialization) {
     auto const stub_kind_name = RawPcDescriptors::KindToCString(stub_kind_);
@@ -890,6 +963,54 @@
   }
 }
 
+SExpression* FlowGraphSerializer::ICDataToSExp(const ICData* ic_data) {
+  auto const sexp = new (zone()) SExpList(zone());
+  AddSymbol(sexp, "ICData");
+
+  if (ic_data->is_tracking_exactness()) {
+    ic_data_type_ = ic_data->receivers_static_type();
+    sexp->AddExtra("receivers_static_type", AbstractTypeToSExp(ic_data_type_));
+  }
+
+  if (ic_data->is_megamorphic() || FLAG_verbose_flow_graph_serialization) {
+    AddExtraBool(sexp, "is_megamorphic", ic_data->is_megamorphic());
+  }
+
+  auto const num_checks = ic_data->NumberOfChecks();
+  GrowableArray<intptr_t> class_ids(zone(), 2);
+  for (intptr_t i = 0; i < num_checks; i++) {
+    auto const entry = new (zone()) SExpList(zone());
+
+    auto const count = ic_data->GetCountAt(i);
+    if (count > 0 || FLAG_verbose_flow_graph_serialization) {
+      AddExtraInteger(entry, "count", count);
+    }
+
+    class_ids.Clear();
+    ic_data->GetCheckAt(i, &class_ids, &ic_data_target_);
+    entry->AddExtra("target", DartValueToSExp(ic_data_target_));
+    for (auto const cid : class_ids) {
+      entry->Add(new (zone()) SExpInteger(cid));
+    }
+
+    sexp->Add(entry);
+  }
+
+  if (FLAG_verbose_flow_graph_serialization) {
+    AddExtraSymbol(sexp, "rebind_rule",
+                   ICData::RebindRuleToCString(ic_data->rebind_rule()));
+    tmp_string_ = ic_data->target_name();
+    AddExtraString(sexp, "target_name", tmp_string_.ToCString());
+    ic_data_target_ = ic_data->Owner();
+    sexp->AddExtra("owner", DartValueToSExp(ic_data_target_));
+    AddExtraInteger(sexp, "num_args_tested", ic_data->NumArgsTested());
+    auto& args_desc = Array::Handle(zone(), ic_data->arguments_descriptor());
+    sexp->AddExtra("arguments_descriptor", DartValueToSExp(args_desc));
+  }
+
+  return sexp;
+}
+
 void TailCallInstr::AddOperandsToSExpression(SExpList* sexp,
                                              FlowGraphSerializer* s) const {
   if (auto const code = s->DartValueToSExp(code_)) {
@@ -905,6 +1026,17 @@
   }
 }
 
+void NativeCallInstr::AddExtraInfoToSExpression(SExpList* sexp,
+                                                FlowGraphSerializer* s) const {
+  TemplateDartCall<0>::AddExtraInfoToSExpression(sexp, s);
+  if (!native_name().IsNull()) {
+    s->AddExtraString(sexp, "name", native_name().ToCString());
+  }
+  if (link_lazily() || FLAG_verbose_flow_graph_serialization) {
+    s->AddExtraBool(sexp, "link_lazily", link_lazily());
+  }
+}
+
 template <intptr_t kInputCount>
 void TemplateDartCall<kInputCount>::AddExtraInfoToSExpression(
     SExpList* sexp,
@@ -914,9 +1046,7 @@
     s->AddExtraInteger(sexp, "type_args_len", type_args_len());
   }
   s->AddExtraInteger(sexp, "args_len", ArgumentCountWithoutTypeArgs());
-  if (this->CallCount() > 0 || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraInteger(sexp, "call_count", this->CallCount());
-  }
+
   const auto& arg_names = argument_names();
   if (!arg_names.IsNull()) {
     auto arg_names_sexp = new (s->zone()) SExpList(s->zone());
@@ -947,12 +1077,28 @@
                                                 FlowGraphSerializer* s) const {
   TemplateDartCall<0>::AddExtraInfoToSExpression(sexp, s);
 
-  if (rebind_rule_ != ICData::kInstance ||
+  if (HasICData()) {
+    sexp->AddExtra("ic_data", s->ICDataToSExp(ic_data()));
+  } else if (CallCount() > 0 || FLAG_verbose_flow_graph_serialization) {
+    s->AddExtraInteger(sexp, "call_count", CallCount());
+  }
+
+  if (rebind_rule_ != ICData::kStatic ||
       FLAG_verbose_flow_graph_serialization) {
     auto const str = ICData::RebindRuleToCString(rebind_rule_);
     ASSERT(str != nullptr);
     s->AddExtraSymbol(sexp, "rebind_rule", str);
   }
+
+  if (ShouldSerializeType(result_type())) {
+    sexp->AddExtra("result_type", result_type()->ToSExpression(s));
+  }
+
+  if (entry_kind() != Code::EntryKind::kNormal ||
+      FLAG_verbose_flow_graph_serialization) {
+    auto const kind_str = Code::EntryKindToCString(entry_kind());
+    s->AddExtraSymbol(sexp, "entry_kind", kind_str);
+  }
 }
 
 void InstanceCallInstr::AddOperandsToSExpression(SExpList* sexp,
@@ -962,17 +1108,54 @@
   }
 }
 
+void InstanceCallInstr::AddExtraInfoToSExpression(
+    SExpList* sexp,
+    FlowGraphSerializer* s) const {
+  TemplateDartCall<0>::AddExtraInfoToSExpression(sexp, s);
+
+  if (HasICData()) {
+    sexp->AddExtra("ic_data", s->ICDataToSExp(ic_data()));
+  }
+
+  if (function_name().IsNull()) {
+    if (!interface_target().IsNull()) {
+      s->AddExtraSymbol(sexp, "function_name", "null");
+    }
+  } else {
+    if (interface_target().IsNull() ||
+        function_name().raw() != interface_target().name()) {
+      s->AddExtraString(sexp, "function_name", function_name().ToCString());
+    }
+  }
+
+  if (token_kind() != Token::kILLEGAL) {
+    s->AddExtraSymbol(sexp, "token_kind", Token::Str(token_kind()));
+  }
+  if (checked_argument_count() > 0 || FLAG_verbose_flow_graph_serialization) {
+    s->AddExtraInteger(sexp, "checked_arg_count", checked_argument_count());
+  }
+
+  if (ShouldSerializeType(result_type())) {
+    sexp->AddExtra("result_type", result_type()->ToSExpression(s));
+  }
+
+  if (entry_kind() != Code::EntryKind::kNormal ||
+      FLAG_verbose_flow_graph_serialization) {
+    auto const kind_str = Code::EntryKindToCString(entry_kind());
+    s->AddExtraSymbol(sexp, "entry_kind", kind_str);
+  }
+}
+
 void PolymorphicInstanceCallInstr::AddOperandsToSExpression(
     SExpList* sexp,
     FlowGraphSerializer* s) const {
-  instance_call()->AddOperandsToSExpression(sexp, s);
+  sexp->Add(instance_call()->ToSExpression(s));
 }
 
 void PolymorphicInstanceCallInstr::AddExtraInfoToSExpression(
     SExpList* sexp,
     FlowGraphSerializer* s) const {
-  ASSERT(deopt_id() == instance_call()->deopt_id());
-  instance_call()->AddExtraInfoToSExpression(sexp, s);
+  Instruction::AddExtraInfoToSExpression(sexp, s);
   if (targets().length() > 0 || FLAG_verbose_flow_graph_serialization) {
     auto elem_list = new (s->zone()) SExpList(s->zone());
     for (intptr_t i = 0; i < targets().length(); i++) {
@@ -1109,45 +1292,52 @@
 
 SExpression* Value::ToSExpression(FlowGraphSerializer* s) const {
   auto name = s->UseToSExp(definition());
-  if (reaching_type_ == nullptr || reaching_type_ == definition()->type_ ||
-      !ShouldSerializeType(reaching_type_)) {
-    return name;
-  }
+  // If we're not serializing types or there is no reaching type for this use,
+  // just serialize the use as the bound name.
+  if (!ShouldSerializeType(reaching_type_)) return name;
+
   auto sexp = new (s->zone()) SExpList(s->zone());
   s->AddSymbol(sexp, "value");
   sexp->Add(name);
-  sexp->AddExtra("type", reaching_type_->ToSExpression(s));
+  // If there is no owner for the type, then serialize the type in full.
+  // Otherwise the owner should be the definition, so we'll inherit the type
+  // from it. (That is, (value v<X>) with no explicit type info means the
+  // reaching type comes from the definition of v<X>.) We'll serialize an
+  // "inherit_type" extra info field to make this explicit when in verbose mode.
+  if (reaching_type_->owner() == nullptr) {
+    sexp->AddExtra("type", reaching_type_->ToSExpression(s));
+  } else {
+    ASSERT(reaching_type_->owner() == definition());
+  }
+  if (FLAG_verbose_flow_graph_serialization) {
+    s->AddExtraBool(sexp, "inherit_type",
+                    reaching_type_->owner() == definition());
+  }
   return sexp;
 }
 
 SExpression* CompileType::ToSExpression(FlowGraphSerializer* s) const {
   ASSERT(FLAG_verbose_flow_graph_serialization ||
          FLAG_serialize_flow_graph_types);
-  ASSERT(cid_ != kDynamicCid || !is_nullable());
 
   auto sexp = new (s->zone()) SExpList(s->zone());
   s->AddSymbol(sexp, "CompileType");
-  if (cid_ != kIllegalCid && cid_ != kDynamicCid) {
-    s->AddInteger(sexp, cid_);
-  }
   AddExtraInfoToSExpression(sexp, s);
   return sexp;
 }
 
 void CompileType::AddExtraInfoToSExpression(SExpList* sexp,
                                             FlowGraphSerializer* s) const {
+  if (cid_ != kIllegalCid || FLAG_verbose_flow_graph_serialization) {
+    s->AddExtraInteger(sexp, "cid", cid_);
+  }
   // TODO(sstrickl): Currently we only print out nullable if it's false
   // (or during verbose printing). Switch this when NNBD is the standard.
   if (!is_nullable() || FLAG_verbose_flow_graph_serialization) {
     s->AddExtraBool(sexp, "nullable", is_nullable());
   }
-  if (cid_ == kIllegalCid || cid_ == kDynamicCid ||
-      FLAG_verbose_flow_graph_serialization) {
-    if (type_ != nullptr) {
-      sexp->AddExtra("type", s->DartValueToSExp(*type_));
-    } else {
-      s->AddExtraString(sexp, "name", ToCString());
-    }
+  if (type_ != nullptr) {
+    sexp->AddExtra("type", s->DartValueToSExp(*type_));
   }
 }
 
diff --git a/runtime/vm/compiler/backend/il_serializer.h b/runtime/vm/compiler/backend/il_serializer.h
index 753ce49..94945e0 100644
--- a/runtime/vm/compiler/backend/il_serializer.h
+++ b/runtime/vm/compiler/backend/il_serializer.h
@@ -95,6 +95,7 @@
   // Methods for serializing IL-specific values.
   SExpression* LocalVariableToSExp(const LocalVariable& v);
   SExpression* SlotToSExp(const Slot& s);
+  SExpression* ICDataToSExp(const ICData* ic_data);
 
   // Helper methods for adding atoms to S-expression lists
   void AddBool(SExpList* sexp, bool b);
@@ -110,6 +111,7 @@
   FlowGraphSerializer(Zone* zone, const FlowGraph* flow_graph)
       : flow_graph_(ASSERT_NOTNULL(flow_graph)),
         zone_(zone),
+        open_recursive_types_(zone_),
         tmp_string_(String::Handle(zone_)),
         array_type_args_((TypeArguments::Handle(zone_))),
         closure_context_(Context::Handle(zone_)),
@@ -119,6 +121,8 @@
         context_parent_(Context::Handle(zone_)),
         context_elem_(Object::Handle(zone_)),
         function_type_args_(TypeArguments::Handle(zone_)),
+        ic_data_target_(Function::Handle(zone_)),
+        ic_data_type_(AbstractType::Handle(zone_)),
         instance_field_(Field::Handle(zone_)),
         instance_type_args_(TypeArguments::Handle(zone_)),
         serialize_library_(Library::Handle(zone_)),
@@ -126,6 +130,7 @@
         serialize_parent_(Function::Handle(zone_)),
         type_arguments_elem_(AbstractType::Handle(zone_)),
         type_class_(Class::Handle(zone_)),
+        type_function_(Function::Handle(zone_)),
         type_ref_type_(AbstractType::Handle(zone_)) {
     // Double-check that the zone in the flow graph is a parent of the
     // zone we'll be using for serialization.
@@ -143,6 +148,10 @@
   const FlowGraph* const flow_graph_;
   Zone* const zone_;
 
+  // A map of currently open (being serialized) recursive types. We use this
+  // to determine whether to serialize the referred types in TypeRefs.
+  IntMap<const Type*> open_recursive_types_;
+
   // Handles used across functions, where the contained value is used
   // immediately and does not need to live across calls to other serializer
   // functions.
@@ -165,6 +174,8 @@
   Context& context_parent_;            // ContextToSExp
   Object& context_elem_;               // ContextToSExp
   TypeArguments& function_type_args_;  // FunctionToSExp
+  Function& ic_data_target_;           // ICDataToSExp
+  AbstractType& ic_data_type_;         // ICDataToSExp
   Field& instance_field_;              // InstanceToSExp
   TypeArguments& instance_type_args_;  // InstanceToSExp
   Library& serialize_library_;         // SerializeCanonicalName
@@ -172,6 +183,7 @@
   Function& serialize_parent_;         // SerializeCanonicalName
   AbstractType& type_arguments_elem_;  // TypeArgumentsToSExp
   Class& type_class_;                  // AbstractTypeToSExp
+  Function& type_function_;            // AbstractTypeToSExp
   AbstractType& type_ref_type_;        // AbstractTypeToSExp
 };
 
diff --git a/runtime/vm/compiler/backend/il_test_helper.cc b/runtime/vm/compiler/backend/il_test_helper.cc
index bdc039a..9570fc9 100644
--- a/runtime/vm/compiler/backend/il_test_helper.cc
+++ b/runtime/vm/compiler/backend/il_test_helper.cc
@@ -46,8 +46,10 @@
 
 void Invoke(const Library& lib, const char* name) {
   // These tests rely on running unoptimized code to collect type feedback. The
-  // interpreter does not collect type feedback for interface calls.
-  SetFlagScope<bool> sfs(&FLAG_enable_interpreter, false);
+  // interpreter does not collect type feedback for interface calls, so set
+  // compilation threshold to 0 in order to compile invoked function
+  // immediately and execute compiled code.
+  SetFlagScope<int> sfs(&FLAG_compilation_counter_threshold, 0);
 
   Thread* thread = Thread::Current();
   Dart_Handle api_lib = Api::NewHandle(thread, lib.raw());
diff --git a/runtime/vm/compiler/backend/il_test_helper.h b/runtime/vm/compiler/backend/il_test_helper.h
index 019b0d5..bdb7be1 100644
--- a/runtime/vm/compiler/backend/il_test_helper.h
+++ b/runtime/vm/compiler/backend/il_test_helper.h
@@ -242,12 +242,11 @@
 
   ConstantInstr* IntConstant(int64_t value) const {
     return flow_graph_.GetConstant(
-        Integer::Handle(Integer::New(value, Heap::kOld)));
+        Integer::Handle(Integer::NewCanonical(value)));
   }
 
   ConstantInstr* DoubleConstant(double value) {
-    return flow_graph_.GetConstant(
-        Double::Handle(Double::New(value, Heap::kOld)));
+    return flow_graph_.GetConstant(Double::Handle(Double::NewCanonical(value)));
   }
 
   PhiInstr* Phi(JoinEntryInstr* join,
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index c7612ed..b7cf98f 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -521,7 +521,9 @@
   compiler->GenerateRuntimeCall(token_pos, deopt_id,
                                 kNonBoolTypeErrorRuntimeEntry, 1, locs);
   // We should never return here.
+#if defined(DEBUG)
   __ int3();
+#endif
   __ Bind(&done);
 }
 
@@ -2893,10 +2895,9 @@
 
 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   __ Bind(compiler->GetJumpLabel(this));
-  compiler->AddExceptionHandler(catch_try_index(), try_index(),
-                                compiler->assembler()->CodeSize(),
-                                handler_token_pos(), is_generated(),
-                                catch_handler_types_, needs_stacktrace());
+  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());
diff --git a/runtime/vm/compiler/backend/sexpression.cc b/runtime/vm/compiler/backend/sexpression.cc
index a314abf..241361e 100644
--- a/runtime/vm/compiler/backend/sexpression.cc
+++ b/runtime/vm/compiler/backend/sexpression.cc
@@ -30,8 +30,12 @@
 }
 
 bool SExpBool::Equals(SExpression* sexp) const {
-  if (!sexp->IsBool()) return false;
-  return this->value() == sexp->AsBool()->value();
+  if (auto const b = sexp->AsBool()) return b->Equals(value());
+  return false;
+}
+
+bool SExpBool::Equals(bool val) const {
+  return value() == val;
 }
 
 void SExpBool::SerializeToLine(TextBuffer* buffer) const {
@@ -40,8 +44,12 @@
 }
 
 bool SExpDouble::Equals(SExpression* sexp) const {
-  if (!sexp->IsDouble()) return false;
-  return this->value() == sexp->AsDouble()->value();
+  if (auto const d = sexp->AsDouble()) return d->Equals(value());
+  return false;
+}
+
+bool SExpDouble::Equals(double val) const {
+  return value() == val;
 }
 
 void SExpDouble::SerializeToLine(TextBuffer* buffer) const {
@@ -53,8 +61,12 @@
 }
 
 bool SExpInteger::Equals(SExpression* sexp) const {
-  if (!sexp->IsInteger()) return false;
-  return this->value() == sexp->AsInteger()->value();
+  if (auto const i = sexp->AsInteger()) return i->Equals(value());
+  return false;
+}
+
+bool SExpInteger::Equals(int64_t val) const {
+  return value() == val;
 }
 
 void SExpInteger::SerializeToLine(TextBuffer* buffer) const {
@@ -62,8 +74,12 @@
 }
 
 bool SExpString::Equals(SExpression* sexp) const {
-  if (!sexp->IsString()) return false;
-  return strcmp(this->value(), sexp->AsString()->value()) == 0;
+  if (auto const s = sexp->AsString()) return s->Equals(value());
+  return false;
+}
+
+bool SExpString::Equals(const char* str) const {
+  return strcmp(value(), str) == 0;
 }
 
 void SExpString::SerializeToLine(TextBuffer* buffer) const {
@@ -73,8 +89,12 @@
 }
 
 bool SExpSymbol::Equals(SExpression* sexp) const {
-  if (!sexp->IsSymbol()) return false;
-  return strcmp(this->value(), sexp->AsSymbol()->value()) == 0;
+  if (auto const s = sexp->AsSymbol()) return s->Equals(value());
+  return false;
+}
+
+bool SExpSymbol::Equals(const char* str) const {
+  return strcmp(value(), str) == 0;
 }
 
 void SExpSymbol::SerializeToLine(TextBuffer* buffer) const {
diff --git a/runtime/vm/compiler/backend/sexpression.h b/runtime/vm/compiler/backend/sexpression.h
index 4a7d67e..d1dfe7e 100644
--- a/runtime/vm/compiler/backend/sexpression.h
+++ b/runtime/vm/compiler/backend/sexpression.h
@@ -115,6 +115,7 @@
         : SExpAtom(start), val_(val) {}                                        \
     value_type value() const { return val_; }                                  \
     virtual bool Equals(SExpression* sexp) const;                              \
+    bool Equals(value_type val) const;                                         \
     virtual void SerializeToLine(TextBuffer* buffer) const;                    \
     DEFINE_S_EXPRESSION_TYPE_CHECK(name)                                       \
    private:                                                                    \
@@ -149,6 +150,13 @@
     return extra_info_.LookupValue(cstr);
   }
 
+  // Shortcut for retrieving the tag from a tagged list (list that contains an
+  // initial symbol). Returns nullptr if the list is not a tagged list.
+  SExpSymbol* Tag() const {
+    if (Length() == 0 || !At(0)->IsSymbol()) return nullptr;
+    return At(0)->AsSymbol();
+  }
+
   DEFINE_S_EXPRESSION_TYPE_CHECK(List)
   virtual bool Equals(SExpression* sexp) const;
   virtual void SerializeTo(Zone* zone,
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index d928420..4a26aa7 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -68,7 +68,7 @@
   }
 }
 
-bool Slot::KindFromCString(const char* str, Kind* out) {
+bool Slot::ParseKind(const char* str, Kind* out) {
   ASSERT(str != nullptr && out != nullptr);
 #define NATIVE_CASE(C, F, id, M)                                               \
   if (strcmp(str, NATIVE_TO_STR(C, F, id, M)) == 0) {                          \
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index 361532b..da23fbd 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -103,7 +103,7 @@
   // clang-format on
 
   static const char* KindToCString(Kind k);
-  static bool KindFromCString(const char* str, Kind* k);
+  static bool ParseKind(const char* str, Kind* k);
 
   // Returns a slot that represents length field for the given [array_cid].
   static const Slot& GetLengthFieldForArrayCid(intptr_t array_cid);
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index 2b70b9d..c6ac8e4 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -951,6 +951,9 @@
         function_name, String::Handle(Z, String::New("#tearoff", Heap::kNew)),
         Heap::kOld);
   }
+  if (!function_name.IsCanonical()) {
+    function_name = Symbols::New(thread_, function_name);
+  }
 
   Fragment call_hook;
   call_hook += Constant(closure);
diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
index a330e14..034716b 100644
--- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
@@ -2013,10 +2013,10 @@
         Array::ZoneHandle(Z, handlers.GetHandledTypes(try_index));
 
     CatchBlockEntryInstr* entry = new (Z) CatchBlockEntryInstr(
-        TokenPosition::kNoSource, handler_info.is_generated != 0,
-        B->AllocateBlockId(), handler_info.outer_try_index, graph_entry,
-        handler_types, try_index, handler_info.needs_stacktrace != 0,
-        B->GetNextDeoptId(), nullptr, nullptr, exception_var_, stacktrace_var_);
+        handler_info.is_generated != 0, B->AllocateBlockId(),
+        handler_info.outer_try_index, graph_entry, handler_types, try_index,
+        handler_info.needs_stacktrace != 0, B->GetNextDeoptId(), nullptr,
+        nullptr, exception_var_, stacktrace_var_);
     graph_entry->AddCatchEntry(entry);
 
     code_ = Fragment(entry);
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index 870a42e..787c06a 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -613,6 +613,13 @@
   const intptr_t num_type_params = reader_.ReadUInt();
   ASSERT(num_type_params > 0);
 
+  intptr_t offset;
+  if (!parameterized_class.IsNull()) {
+    offset = parameterized_class.NumTypeArguments() - num_type_params;
+  } else {
+    offset = parameterized_function.NumParentTypeParameters();
+  }
+
   // First setup the type parameters, so if any of the following code uses it
   // (in a recursive way) we're fine.
   //
@@ -628,6 +635,8 @@
     parameter = TypeParameter::New(
         parameterized_class, parameterized_function, i, name, bound,
         /* is_generic_covariant_impl = */ false, TokenPosition::kNoSource);
+    parameter.set_index(offset + i);
+    parameter.SetIsFinalized();
     type_parameters.SetTypeAt(i, parameter);
   }
 
@@ -984,15 +993,14 @@
                                          TokenPosition::kNoSource, try_index);
       pc_descriptors_list->AddDescriptor(RawPcDescriptors::kOther, end_pc,
                                          DeoptId::kNone,
-                                         TokenPosition::kNoSource, -1);
+                                         TokenPosition::kNoSource, try_index);
 
       // The exception handler keeps a zone handle of the types array, rather
       // than a raw pointer. Do not share the handle across iterations to avoid
       // clobbering the array.
       exception_handlers_list->AddHandler(
-          try_index, outer_try_index, handler_pc, TokenPosition::kNoSource,
-          is_generated, Array::ZoneHandle(Z, handler_types.raw()),
-          needs_stacktrace);
+          try_index, outer_try_index, handler_pc, is_generated,
+          Array::ZoneHandle(Z, handler_types.raw()), needs_stacktrace);
     }
     const PcDescriptors& descriptors = PcDescriptors::Handle(
         Z, pc_descriptors_list->FinalizePcDescriptors(bytecode.PayloadStart()));
@@ -1622,7 +1630,9 @@
       return AbstractType::void_type().raw();
     case kSimpleType: {
       const Class& cls = Class::CheckedHandle(Z, ReadObject());
-      cls.EnsureDeclarationLoaded();
+      if (!cls.is_declaration_loaded()) {
+        LoadReferencedClass(cls);
+      }
       return cls.DeclarationType();
     }
     case kTypeParameter: {
@@ -1646,14 +1656,13 @@
       } else {
         UNREACHABLE();
       }
-      AbstractType& type =
-          AbstractType::Handle(Z, type_parameters.TypeAt(index_in_parent));
-      // TODO(alexmarkov): skip type finalization
-      return ClassFinalizer::FinalizeType(*active_class_->klass, type);
+      return type_parameters.TypeAt(index_in_parent);
     }
     case kGenericType: {
       const Class& cls = Class::CheckedHandle(Z, ReadObject());
-      cls.EnsureDeclarationLoaded();
+      if (!cls.is_declaration_loaded()) {
+        LoadReferencedClass(cls);
+      }
       const TypeArguments& type_arguments =
           TypeArguments::CheckedHandle(Z, ReadObject());
       const Type& type = Type::Handle(
@@ -1664,7 +1673,9 @@
     case kRecursiveGenericType: {
       const intptr_t id = reader_.ReadUInt();
       const Class& cls = Class::CheckedHandle(Z, ReadObject());
-      cls.EnsureDeclarationLoaded();
+      if (!cls.is_declaration_loaded()) {
+        LoadReferencedClass(cls);
+      }
       const auto saved_pending_recursive_types = pending_recursive_types_;
       if (id == 0) {
         pending_recursive_types_ = &GrowableObjectArray::Handle(
@@ -1808,16 +1819,17 @@
     source = ReadString(/* is_canonical = */ false);
   }
 
-  if (source.IsNull() && line_starts.IsNull()) {
-    // This script provides a uri only, but no source or line_starts array.
-    // The source is set to the empty symbol, indicating that source and
-    // line_starts array are lazily looked up if needed.
-    source = Symbols::Empty().raw();  // Lookup is postponed.
-  }
-
   const Script& script = Script::Handle(
       Z, Script::New(import_uri, uri, source, RawScript::kKernelTag));
   script.set_line_starts(line_starts);
+
+  if (source.IsNull() && line_starts.IsNull()) {
+    // This script provides a uri only, but no source or line_starts array.
+    // This could be a reference to a Script in another kernel binary.
+    // Make an attempt to find source and line starts when needed.
+    script.SetLazyLookupSourceAndLineStarts(true);
+  }
+
   return script.raw();
 }
 
@@ -2301,6 +2313,27 @@
   functions_ = nullptr;
 }
 
+void BytecodeReaderHelper::LoadReferencedClass(const Class& cls) {
+  ASSERT(!cls.is_declaration_loaded());
+
+  if (!cls.is_declared_in_bytecode()) {
+    cls.EnsureDeclarationLoaded();
+    return;
+  }
+
+  const auto& script = Script::Handle(Z, cls.script());
+  if (H.GetKernelProgramInfo().raw() != script.kernel_program_info()) {
+    // Class comes from a different binary.
+    cls.EnsureDeclarationLoaded();
+    return;
+  }
+
+  // We can reuse current BytecodeReaderHelper.
+  ActiveClassScope active_class_scope(active_class_, &cls);
+  AlternativeReadingScope alt(&reader_, cls.bytecode_offset());
+  ReadClassDeclaration(cls);
+}
+
 void BytecodeReaderHelper::ReadClassDeclaration(const Class& cls) {
   // Class flags, must be in sync with ClassDeclaration constants in
   // pkg/vm/lib/bytecode/declarations.dart.
@@ -2769,10 +2802,8 @@
                              Function::Handle(Z, function.parent_function()));
       return;
     case RawFunction::kDynamicInvocationForwarder:
-      ParseForwarderFunction(
-          parsed_function, function,
-          Function::Handle(Z,
-                           function.GetTargetOfDynamicInvocationForwarder()));
+      ParseForwarderFunction(parsed_function, function,
+                             Function::Handle(Z, function.ForwardingTarget()));
       return;
     case RawFunction::kImplicitGetter:
     case RawFunction::kImplicitSetter:
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.h b/runtime/vm/compiler/frontend/bytecode_reader.h
index ec915dd..39951e5 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.h
+++ b/runtime/vm/compiler/frontend/bytecode_reader.h
@@ -225,6 +225,10 @@
            expression_evaluation_library_->raw() == library.raw();
   }
 
+  // Similar to cls.EnsureClassDeclaration, but may be more efficient if
+  // class is from the current kernel binary.
+  void LoadReferencedClass(const Class& cls);
+
   Reader reader_;
   TranslationHelper& translation_helper_;
   ActiveClass* const active_class_;
@@ -436,10 +440,11 @@
   }
 
   bool MoveNext() {
-    if (entries_remaining_ == 0) {
+    if (entries_remaining_ <= 0) {
+      // Finished looking at the last entry, now we're done.
+      entries_remaining_ = -1;
       return false;
     }
-    ASSERT(entries_remaining_ > 0);
     --entries_remaining_;
     cur_kind_and_flags_ = reader_.ReadByte();
     cur_start_pc_ += reader_.ReadSLEB128();
@@ -464,7 +469,10 @@
     return true;
   }
 
-  bool IsDone() const { return entries_remaining_ == 0; }
+  // Returns true after iterator moved past the last entry and
+  // MoveNext() returned false.
+  bool IsDone() const { return entries_remaining_ < 0; }
+
   intptr_t Kind() const { return cur_kind_and_flags_ & kKindMask; }
   bool IsScope() const { return Kind() == kScope; }
   bool IsVariableDeclaration() const { return Kind() == kVariableDeclaration; }
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 1cfab97..9fb9b27 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -232,7 +232,8 @@
             ExternalTypedData::Handle(Z, class_field.KernelData());
         ASSERT(!kernel_data.IsNull());
         intptr_t field_offset = class_field.kernel_offset();
-        AlternativeReadingScope alt(&reader_, &kernel_data, field_offset);
+        AlternativeReadingScopeWithNewData alt(&reader_, &kernel_data,
+                                               field_offset);
         FieldHelper field_helper(this);
         field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
         Tag initializer_tag = ReadTag();  // read first part of initializer.
@@ -3720,8 +3721,7 @@
 
   const String& value =
       H.DartString(ReadStringReference());  // read index into string table.
-  const Integer& integer =
-      Integer::ZoneHandle(Z, Integer::New(value, Heap::kOld));
+  const Integer& integer = Integer::ZoneHandle(Z, Integer::NewCanonical(value));
   if (integer.IsNull()) {
     H.ReportError(script_, TokenPosition::kNoSource,
                   "Integer literal %s is out of range", value.ToCString());
@@ -4768,6 +4768,10 @@
 
   ASSERT(flags == kNativeYieldFlags);  // Must have been desugared.
 
+  // Collect yield position
+  if (record_yield_positions_ != nullptr) {
+    record_yield_positions_->Add(Smi::Handle(Z, Smi::New(position.value())));
+  }
   // Setup yield/continue point:
   //
   //   ...
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 0eab5b9b..2cdbb28 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -21,9 +21,11 @@
 
 class StreamingFlowGraphBuilder : public KernelReaderHelper {
  public:
-  StreamingFlowGraphBuilder(FlowGraphBuilder* flow_graph_builder,
-                            const ExternalTypedData& data,
-                            intptr_t data_program_offset)
+  StreamingFlowGraphBuilder(
+      FlowGraphBuilder* flow_graph_builder,
+      const ExternalTypedData& data,
+      intptr_t data_program_offset,
+      GrowableObjectArray* record_yield_positions = nullptr)
       : KernelReaderHelper(
             flow_graph_builder->zone_,
             &flow_graph_builder->translation_helper_,
@@ -44,7 +46,8 @@
         inferred_type_metadata_helper_(this),
         procedure_attributes_metadata_helper_(this),
         call_site_attributes_metadata_helper_(this, &type_translator_),
-        closure_owner_(Object::Handle(flow_graph_builder->zone_)) {}
+        closure_owner_(Object::Handle(flow_graph_builder->zone_)),
+        record_yield_positions_(record_yield_positions) {}
 
   virtual ~StreamingFlowGraphBuilder() {}
 
@@ -367,6 +370,7 @@
   ProcedureAttributesMetadataHelper procedure_attributes_metadata_helper_;
   CallSiteAttributesMetadataHelper call_site_attributes_metadata_helper_;
   Object& closure_owner_;
+  GrowableObjectArray* record_yield_positions_;
 
   friend class KernelLoader;
 
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index fbca763..4748658 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -40,7 +40,8 @@
     bool optimizing,
     intptr_t osr_id,
     intptr_t first_block_id,
-    bool inlining_unchecked_entry)
+    bool inlining_unchecked_entry,
+    GrowableObjectArray* record_yield_positions)
     : BaseFlowGraphBuilder(parsed_function,
                            first_block_id - 1,
                            osr_id,
@@ -68,6 +69,7 @@
       catch_block_(NULL) {
   const Script& script =
       Script::Handle(Z, parsed_function->function().script());
+  record_yield_positions_ = record_yield_positions;
   H.InitFromScript(script);
 }
 
@@ -226,7 +228,6 @@
   LocalVariable* raw_stacktrace_var = CurrentRawStackTrace();
 
   CatchBlockEntryInstr* entry = new (Z) CatchBlockEntryInstr(
-      TokenPosition::kNoSource,  // Token position of catch block.
       is_synthesized,  // whether catch block was synthesized by FE compiler
       AllocateBlockId(), CurrentTryIndex(), graph_entry_, handler_types,
       handler_index, needs_stacktrace, GetNextDeoptId(), exception_var,
@@ -643,7 +644,7 @@
   // TODO(alexmarkov): refactor this - StreamingFlowGraphBuilder should not be
   //  used for bytecode functions.
   StreamingFlowGraphBuilder streaming_flow_graph_builder(
-      this, kernel_data, kernel_data_program_offset);
+      this, kernel_data, kernel_data_program_offset, record_yield_positions_);
   return streaming_flow_graph_builder.BuildGraph();
 }
 
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index 0b9d2fe..3775000 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -56,7 +56,8 @@
                    bool optimizing,
                    intptr_t osr_id,
                    intptr_t first_block_id = 1,
-                   bool inlining_unchecked_entry = false);
+                   bool inlining_unchecked_entry = false,
+                   GrowableObjectArray* record_yield_position = nullptr);
   virtual ~FlowGraphBuilder();
 
   FlowGraph* BuildGraph();
@@ -377,6 +378,8 @@
 
   ActiveClass active_class_;
 
+  GrowableObjectArray* record_yield_positions_;
+
   friend class BreakableBlock;
   friend class CatchBlock;
   friend class ConstantEvaluator;
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 4469fce..771d4ce 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -1623,8 +1623,8 @@
     return false;
   }
 
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              md_offset);
+  AlternativeReadingScopeWithNewData alt(&helper_->reader_,
+                                         &H.metadata_payloads(), md_offset);
 
   *target_name = helper_->ReadCanonicalNameReference();
   *check_receiver_for_null = helper_->ReadBool();
@@ -1701,8 +1701,8 @@
                                 InferredTypeMetadata::kFlagNullable);
   }
 
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              md_offset);
+  AlternativeReadingScopeWithNewData alt(&helper_->reader_,
+                                         &H.metadata_payloads(), md_offset);
 
   const NameIndex kernel_name = helper_->ReadCanonicalNameReference();
   const uint8_t flags = helper_->ReadByte();
@@ -1737,8 +1737,8 @@
     return false;
   }
 
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              md_offset);
+  AlternativeReadingScopeWithNewData alt(&helper_->reader_,
+                                         &H.metadata_payloads(), md_offset);
 
   const int kDynamicUsesBit = 1 << 0;
   const int kNonThisUsesBit = 1 << 1;
@@ -1771,8 +1771,8 @@
     return;
   }
 
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              md_offset);
+  AlternativeReadingScopeWithNewData alt(&helper_->reader_,
+                                         &H.metadata_payloads(), md_offset);
   Obfuscator O(Thread::Current(), String::Handle());
 
   intptr_t len = helper_->ReadUInt32();
@@ -1797,8 +1797,8 @@
     return false;
   }
 
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              md_offset);
+  AlternativeReadingScopeWithNewData alt(&helper_->reader_,
+                                         &H.metadata_payloads(), md_offset);
 
   metadata->receiver_type = &type_translator_.BuildType();
   return true;
@@ -2475,8 +2475,7 @@
       SkipStatement();  // read finalizer.
       return;
     case kYieldStatement: {
-      TokenPosition position = ReadPosition();  // read position.
-      RecordYieldPosition(position);
+      ReadPosition();    // read position.
       ReadByte();        // read flags.
       SkipExpression();  // read expression.
       return;
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index 8f9371b..6187caa 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -1036,12 +1036,6 @@
     USE(id);
   }
 
-  virtual void RecordYieldPosition(TokenPosition position) {
-    // Do nothing by default.
-    // This is overridden in KernelTokenPositionCollector.
-    USE(position);
-  }
-
   virtual void RecordTokenPosition(TokenPosition position) {
     // Do nothing by default.
     // This is overridden in KernelTokenPositionCollector.
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index 8e4a4c6..2866061 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -188,8 +188,8 @@
                   ExternalTypedData::Handle(Z, class_field.KernelData());
               ASSERT(!kernel_data.IsNull());
               intptr_t field_offset = class_field.kernel_offset();
-              AlternativeReadingScope alt(&helper_.reader_, &kernel_data,
-                                          field_offset);
+              AlternativeReadingScopeWithNewData alt(
+                  &helper_.reader_, &kernel_data, field_offset);
               FieldHelper field_helper(&helper_);
               field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
               Tag initializer_tag =
@@ -473,8 +473,8 @@
             ExternalTypedData::Handle(Z, class_field.KernelData());
         ASSERT(!kernel_data.IsNull());
         intptr_t field_offset = class_field.kernel_offset();
-        AlternativeReadingScope alt(&helper_.reader_, &kernel_data,
-                                    field_offset);
+        AlternativeReadingScopeWithNewData alt(&helper_.reader_, &kernel_data,
+                                               field_offset);
         FieldHelper field_helper(&helper_);
         field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
         Tag initializer_tag = helper_.ReadTag();
@@ -1739,7 +1739,8 @@
   ASSERT(!kernel_data.IsNull());
 
   // Temporarily go to the variable declaration, read the name.
-  AlternativeReadingScope alt(&helper_.reader_, &kernel_data, kernel_offset);
+  AlternativeReadingScopeWithNewData alt(&helper_.reader_, &kernel_data,
+                                         kernel_offset);
   VariableDeclarationHelper helper(&helper_);
   helper.ReadUntilIncluding(VariableDeclarationHelper::kNameIndex);
   return helper.name_index_;
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index 5bf7d0a..dd25e7a 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -230,14 +230,14 @@
         Exceptions::PropagateError(Error::Cast(result));
       }
     }
-    if (function.HasBytecode()) {
+    if (function.HasBytecode() && (FLAG_compilation_counter_threshold != 0)) {
       // If interpreter is enabled and there is bytecode, LazyCompile stub
       // (which calls CompileFunction) should proceed to InterpretCall in order
       // to enter interpreter. In such case, compilation is postponed and
       // triggered by interpreter later via CompileInterpretedFunction.
       return;
     }
-    // No bytecode, fall back to compilation.
+    // Fall back to compilation.
   } else {
     ASSERT(!function.HasCode());
   }
@@ -646,26 +646,32 @@
       }
       {
         TIMELINE_DURATION(thread(), CompilerVerbose, "FinalizeCompilation");
-        if (thread()->IsMutatorThread()) {
+
+        auto install_code_fun = [&]() {
           *result =
               FinalizeCompilation(&assembler, &graph_compiler, flow_graph);
-        } else {
-          // This part of compilation must be at a safepoint.
-          // Stop mutator thread before creating the instruction object and
-          // installing code.
-          // Mutator thread may not run code while we are creating the
-          // instruction object, since the creation of instruction object
-          // changes code page access permissions (makes them temporary not
-          // executable).
-          {
-            CheckIfBackgroundCompilerIsBeingStopped(optimized());
-            ForceGrowthSafepointOperationScope safepoint_scope(thread());
-            CheckIfBackgroundCompilerIsBeingStopped(optimized());
-            *result =
-                FinalizeCompilation(&assembler, &graph_compiler, flow_graph);
-          }
+        };
+
+        if (Compiler::IsBackgroundCompilation()) {
+          CheckIfBackgroundCompilerIsBeingStopped(optimized());
         }
 
+        // We have to ensure no mutators are running, because:
+        //
+        //   a) We allocate an instructions object, which might cause us to
+        //      temporarily flip page protections (RX -> RW -> RX).
+        //
+        //   b) We have to ensure the code generated does not violate
+        //      assumptions (e.g. CHA, field guards), the validation has to
+        //      happen while mutator is stopped.
+        //
+        //   b) We update the [Function] object with a new [Code] which
+        //      requires updating several pointers: We have to ensure all of
+        //      those writes are observed atomically.
+        //
+        thread()->isolate_group()->RunWithStoppedMutators(
+            install_code_fun, install_code_fun, /*use_force_growth=*/true);
+
         // We notify code observers after finalizing the code in order to be
         // outside a [SafepointOperationScope].
         Code::NotifyCodeObservers(function, *result, optimized());
@@ -1012,6 +1018,41 @@
   }
 }
 
+void Compiler::ComputeYieldPositions(const Function& function) {
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  const Script& script = Script::Handle(zone, function.script());
+  Array& yield_position_map = Array::Handle(zone, script.yield_positions());
+  if (yield_position_map.IsNull()) {
+    yield_position_map = HashTables::New<UnorderedHashMap<SmiTraits>>(4);
+  }
+  UnorderedHashMap<SmiTraits> function_map(yield_position_map.raw());
+  Smi& key = Smi::Handle(zone, Smi::New(function.token_pos().value()));
+
+  if (function_map.ContainsKey(key)) {
+    ASSERT(function_map.Release().raw() == yield_position_map.raw());
+    return;
+  }
+
+  CompilerState state(thread);
+  LongJumpScope jump;
+  auto& array = GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
+  if (setjmp(*jump.Set()) == 0) {
+    ParsedFunction* parsed_function =
+        new ParsedFunction(thread, Function::ZoneHandle(zone, function.raw()));
+    ZoneGrowableArray<const ICData*>* ic_data_array =
+        new ZoneGrowableArray<const ICData*>();
+    kernel::FlowGraphBuilder builder(parsed_function, ic_data_array, nullptr,
+                                     /* not inlining */ nullptr, false,
+                                     Compiler::kNoOSRDeoptId, 1, false, &array);
+    builder.BuildGraph();
+  }
+  function_map.UpdateOrInsert(key, array);
+  // Release and store back to script
+  yield_position_map = function_map.Release().raw();
+  script.set_yield_positions(yield_position_map);
+}
+
 RawError* Compiler::CompileAllFunctions(const Class& cls) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
@@ -1412,6 +1453,10 @@
   UNREACHABLE();
 }
 
+void Compiler::ComputeYieldPositions(const Function& function) {
+  UNREACHABLE();
+}
+
 RawError* Compiler::CompileAllFunctions(const Class& cls) {
   FATAL1("Attempt to compile class %s", cls.ToCString());
   return Error::null();
diff --git a/runtime/vm/compiler/jit/compiler.h b/runtime/vm/compiler/jit/compiler.h
index 123e16a..94e22b7 100644
--- a/runtime/vm/compiler/jit/compiler.h
+++ b/runtime/vm/compiler/jit/compiler.h
@@ -108,6 +108,8 @@
   // Generates local var descriptors and sets it in 'code'. Do not call if the
   // local var descriptor already exists.
   static void ComputeLocalVarDescriptors(const Code& code);
+  // Collect yield positions for function and store into its script object
+  static void ComputeYieldPositions(const Function& function);
 
   // Eagerly compiles all functions in a class.
   //
diff --git a/runtime/vm/compiler/relocation.cc b/runtime/vm/compiler/relocation.cc
index af363e6..feb31a3 100644
--- a/runtime/vm/compiler/relocation.cc
+++ b/runtime/vm/compiler/relocation.cc
@@ -23,7 +23,7 @@
 
 // The trampolines will have a 1-word object header in front of them.
 const intptr_t kOffsetInTrampoline = kWordSize;
-const intptr_t kTrampolineSize = OS::kMaxPreferredCodeAlignment;
+const intptr_t kTrampolineSize = 32;
 
 CodeRelocator::CodeRelocator(Thread* thread,
                              GrowableArray<RawCode*>* code_objects,
@@ -33,7 +33,16 @@
       commands_(commands),
       kind_type_and_offset_(Smi::Handle(thread->zone())),
       target_(Object::Handle(thread->zone())),
-      destination_(Code::Handle(thread->zone())) {}
+      destination_(Code::Handle(thread->zone())) {
+  // Trampolines will be disguised as FreeListElement objects.
+  ASSERT(Utils::IsAligned(kTrampolineSize, kObjectAlignment));
+  // Trampolines will be inserted between Instructions objects and must
+  // preserve their alignment.
+  ASSERT(Utils::IsAligned(kTrampolineSize, OS::PreferredCodeAlignment()));
+  // Trampolines are big enough to hold a full-range call.
+  ASSERT((kOffsetInTrampoline +
+          PcRelativeTrampolineJumpPattern::kLengthInBytes) < kTrampolineSize);
+}
 
 void CodeRelocator::Relocate(bool is_vm_isolate) {
   Zone* zone = Thread::Current()->zone();
@@ -408,7 +417,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 +478,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,
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index e7f6f80..88ad78e 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -508,7 +508,6 @@
   intptr_t alignment = OS::PreferredCodeAlignment();
   intptr_t aligned_size =
       Utils::RoundUp(Instructions::UnalignedHeaderSize(), alignment);
-  ASSERT(aligned_size == alignment);
   return aligned_size;
 }
 
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index add5eab..3e93b40 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -355,7 +355,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;
@@ -714,7 +714,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 =
-    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;
@@ -1065,7 +1065,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;
@@ -1425,7 +1425,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 =
-    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;
@@ -1712,7 +1712,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 =
-    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;
@@ -1996,7 +1996,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;
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index 16746a5..59674e3 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -222,6 +222,8 @@
 
   __ PopRegisters(all_registers);
   __ LeaveFrame();
+
+  __ mov(CSP, SP);
   __ Ret();
 }
 
@@ -249,6 +251,8 @@
 
   __ PopRegisters(all_registers);
   __ LeaveFrame();
+
+  __ mov(CSP, SP);
   __ Ret();
 }
 
@@ -395,7 +399,7 @@
 
   // EnterSafepoint clobbers TMP, TMP2 and R8 -- all volatile and not holding
   // return values.
-  __ EnterSafepoint(R8);
+  __ EnterSafepoint(/*scratch=*/R8);
 
   // Pop LR and THR from the real stack (CSP).
   __ ldp(THR, LR, Address(CSP, 2 * target::kWordSize, Address::PairPostIndex));
@@ -872,7 +876,7 @@
   __ AddImmediate(R1, -target::kWordSize);
   __ AddImmediate(R3, target::kWordSize);
   __ AddImmediateSetFlags(R2, R2, -target::ToRawSmi(1));
-  __ str(R7, Address(R3, -target::kWordSize));
+  __ StoreIntoObject(R0, Address(R3, -target::kWordSize), R7);
   __ b(&loop, GE);
   __ Bind(&loop_exit);
 }
diff --git a/runtime/vm/cpu_ia32.cc b/runtime/vm/cpu_ia32.cc
index 82ab263..a2ed128 100644
--- a/runtime/vm/cpu_ia32.cc
+++ b/runtime/vm/cpu_ia32.cc
@@ -27,21 +27,23 @@
   return "ia32";
 }
 
+const char* HostCPUFeatures::hardware_ = nullptr;
 bool HostCPUFeatures::sse2_supported_ = false;
 bool HostCPUFeatures::sse4_1_supported_ = false;
-const char* HostCPUFeatures::hardware_ = NULL;
+bool HostCPUFeatures::popcnt_supported_ = false;
+bool HostCPUFeatures::abm_supported_ = false;
 #if defined(DEBUG)
 bool HostCPUFeatures::initialized_ = false;
 #endif
 
 void HostCPUFeatures::Init() {
   CpuInfo::Init();
-
   hardware_ = CpuInfo::GetCpuModel();
   sse2_supported_ = CpuInfo::FieldContains(kCpuInfoFeatures, "sse2");
   sse4_1_supported_ = CpuInfo::FieldContains(kCpuInfoFeatures, "sse4_1") ||
                       CpuInfo::FieldContains(kCpuInfoFeatures, "sse4.1");
-
+  popcnt_supported_ = CpuInfo::FieldContains(kCpuInfoFeatures, "popcnt");
+  abm_supported_ = CpuInfo::FieldContains(kCpuInfoFeatures, "abm");
 #if defined(DEBUG)
   initialized_ = true;
 #endif
diff --git a/runtime/vm/cpu_ia32.h b/runtime/vm/cpu_ia32.h
index a740fb5..f622c1f 100644
--- a/runtime/vm/cpu_ia32.h
+++ b/runtime/vm/cpu_ia32.h
@@ -32,13 +32,21 @@
     DEBUG_ASSERT(initialized_);
     return sse4_1_supported_ && FLAG_use_sse41;
   }
+  static bool popcnt_supported() {
+    DEBUG_ASSERT(initialized_);
+    return popcnt_supported_;
+  }
+  static bool abm_supported() {
+    DEBUG_ASSERT(initialized_);
+    return abm_supported_;
+  }
 
  private:
-  static const uint64_t kSSE2BitMask = static_cast<uint64_t>(1) << 26;
-  static const uint64_t kSSE4_1BitMask = static_cast<uint64_t>(1) << 51;
   static const char* hardware_;
   static bool sse2_supported_;
   static bool sse4_1_supported_;
+  static bool popcnt_supported_;
+  static bool abm_supported_;
 #if defined(DEBUG)
   static bool initialized_;
 #endif
@@ -51,6 +59,8 @@
   static const char* hardware() { return HostCPUFeatures::hardware(); }
   static bool sse2_supported() { return HostCPUFeatures::sse2_supported(); }
   static bool sse4_1_supported() { return HostCPUFeatures::sse4_1_supported(); }
+  static bool popcnt_supported() { return HostCPUFeatures::popcnt_supported(); }
+  static bool abm_supported() { return HostCPUFeatures::abm_supported(); }
   static bool double_truncate_round_supported() { return sse4_1_supported(); }
 };
 
diff --git a/runtime/vm/cpu_x64.cc b/runtime/vm/cpu_x64.cc
index a4a17f1..c892d85 100644
--- a/runtime/vm/cpu_x64.cc
+++ b/runtime/vm/cpu_x64.cc
@@ -27,9 +27,12 @@
   return "x64";
 }
 
+const char* HostCPUFeatures::hardware_ = nullptr;
 bool HostCPUFeatures::sse2_supported_ = true;
 bool HostCPUFeatures::sse4_1_supported_ = false;
-const char* HostCPUFeatures::hardware_ = NULL;
+bool HostCPUFeatures::popcnt_supported_ = false;
+bool HostCPUFeatures::abm_supported_ = false;
+
 #if defined(DEBUG)
 bool HostCPUFeatures::initialized_ = false;
 #endif
@@ -39,7 +42,8 @@
   hardware_ = CpuInfo::GetCpuModel();
   sse4_1_supported_ = CpuInfo::FieldContains(kCpuInfoFeatures, "sse4_1") ||
                       CpuInfo::FieldContains(kCpuInfoFeatures, "sse4.1");
-
+  popcnt_supported_ = CpuInfo::FieldContains(kCpuInfoFeatures, "popcnt");
+  abm_supported_ = CpuInfo::FieldContains(kCpuInfoFeatures, "abm");
 #if defined(DEBUG)
   initialized_ = true;
 #endif
diff --git a/runtime/vm/cpu_x64.h b/runtime/vm/cpu_x64.h
index e87d2d5..6e6cf83 100644
--- a/runtime/vm/cpu_x64.h
+++ b/runtime/vm/cpu_x64.h
@@ -32,13 +32,21 @@
     DEBUG_ASSERT(initialized_);
     return sse4_1_supported_ && FLAG_use_sse41;
   }
+  static bool popcnt_supported() {
+    DEBUG_ASSERT(initialized_);
+    return popcnt_supported_;
+  }
+  static bool abm_supported() {
+    DEBUG_ASSERT(initialized_);
+    return abm_supported_;
+  }
 
  private:
-  static const uint64_t kSSE2BitMask = static_cast<uint64_t>(1) << 26;
-  static const uint64_t kSSE4_1BitMask = static_cast<uint64_t>(1) << 51;
   static const char* hardware_;
   static bool sse2_supported_;
   static bool sse4_1_supported_;
+  static bool popcnt_supported_;
+  static bool abm_supported_;
 #if defined(DEBUG)
   static bool initialized_;
 #endif
@@ -51,6 +59,8 @@
   static const char* hardware() { return HostCPUFeatures::hardware(); }
   static bool sse2_supported() { return HostCPUFeatures::sse2_supported(); }
   static bool sse4_1_supported() { return HostCPUFeatures::sse4_1_supported(); }
+  static bool popcnt_supported() { return HostCPUFeatures::popcnt_supported(); }
+  static bool abm_supported() { return HostCPUFeatures::abm_supported(); }
   static bool double_truncate_round_supported() { return false; }
 };
 
diff --git a/runtime/vm/cpuid.cc b/runtime/vm/cpuid.cc
index ce80696..ce6b13f 100644
--- a/runtime/vm/cpuid.cc
+++ b/runtime/vm/cpuid.cc
@@ -19,8 +19,11 @@
 
 bool CpuId::sse2_ = false;
 bool CpuId::sse41_ = false;
-const char* CpuId::id_string_ = NULL;
-const char* CpuId::brand_string_ = NULL;
+bool CpuId::popcnt_ = false;
+bool CpuId::abm_ = false;
+
+const char* CpuId::id_string_ = nullptr;
+const char* CpuId::brand_string_ = nullptr;
 
 #if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
 
@@ -39,6 +42,7 @@
 
   GetCpuId(0, info);
   char* id_string = reinterpret_cast<char*>(malloc(3 * sizeof(int32_t)));
+
   // Yes, these are supposed to be out of order.
   *reinterpret_cast<uint32_t*>(id_string) = info[1];
   *reinterpret_cast<uint32_t*>(id_string + 4) = info[3];
@@ -48,6 +52,10 @@
   GetCpuId(1, info);
   CpuId::sse41_ = (info[2] & (1 << 19)) != 0;
   CpuId::sse2_ = (info[3] & (1 << 26)) != 0;
+  CpuId::popcnt_ = (info[2] & (1 << 23)) != 0;
+
+  GetCpuId(0x80000001, info);
+  CpuId::abm_ = (info[2] & (1 << 5)) != 0;
 
   char* brand_string =
       reinterpret_cast<char*>(malloc(3 * 4 * sizeof(uint32_t)));
@@ -89,15 +97,25 @@
     case kCpuInfoHardware:
       return brand_string();
     case kCpuInfoFeatures: {
-      if (sse2() && sse41()) {
-        return strdup("sse2 sse4.1");
-      } else if (sse2()) {
-        return strdup("sse2");
-      } else if (sse41()) {
-        return strdup("sse4.1");
-      } else {
-        return strdup("");
+      char buffer[100];
+      char* p = buffer;
+      const char* q = p + 100;
+      *p = '\0';
+      if (sse2()) {
+        p += snprintf(p, q - p, "sse2 ");
       }
+      if (sse41()) {
+        p += snprintf(p, q - p, "sse4.1 ");
+      }
+      if (popcnt()) {
+        p += snprintf(p, q - p, "popcnt ");
+      }
+      if (abm()) {
+        p += snprintf(p, q - p, "abm ");
+      }
+      // Remove last space before returning string.
+      if (p != buffer) *(p - 1) = '\0';
+      return strdup(buffer);
     }
     default: {
       UNREACHABLE();
diff --git a/runtime/vm/cpuid.h b/runtime/vm/cpuid.h
index fb7ff70..99f4f34 100644
--- a/runtime/vm/cpuid.h
+++ b/runtime/vm/cpuid.h
@@ -23,7 +23,7 @@
 #else
   static void Init() {}
   static void Cleanup() {}
-  static const char* field(CpuInfoIndices idx) { return NULL; }
+  static const char* field(CpuInfoIndices idx) { return nullptr; }
 #endif
 
  private:
@@ -33,9 +33,13 @@
 
   static bool sse2() { return sse2_; }
   static bool sse41() { return sse41_; }
+  static bool popcnt() { return popcnt_; }
+  static bool abm() { return abm_; }
 
   static bool sse2_;
   static bool sse41_;
+  static bool popcnt_;
+  static bool abm_;
   static const char* id_string_;
   static const char* brand_string_;
 
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 5d444dc..437ce00 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -7912,7 +7912,7 @@
 TEST_CASE(DartAPI_InvokeImportedFunction) {
   const char* kScriptChars =
       "import 'dart:math';\n"
-      "import 'dart:profiler';\n"
+      "import 'dart:developer';\n"
       "main() {}";
   Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
   EXPECT_VALID(lib);
@@ -7924,11 +7924,6 @@
   EXPECT_ERROR(result,
                "NoSuchMethodError: No top-level method 'max' declared.");
 
-  // The function 'getCurrentTag' is actually defined in the library
-  // dart:developer. However, the library dart:profiler exports dart:developer
-  // and exposes the function 'getCurrentTag'.
-  // NOTE: dart:profiler is deprecated. So, its use in this test is only
-  // an interim solution until we fix DartAPI_Invoke_CrossLibrary.
   Dart_Handle getCurrentTag = Dart_NewStringFromCString("getCurrentTag");
   result = Dart_Invoke(lib, getCurrentTag, 0, NULL);
   EXPECT_ERROR(
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 4bd384c..749f567 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -152,7 +152,7 @@
       }
 
       // If we have bytecode but no native code then invoke the interpreter.
-      if (function.HasBytecode()) {
+      if (function.HasBytecode() && (FLAG_compilation_counter_threshold != 0)) {
         ASSERT(thread->no_callback_scope_depth() == 0);
         SuspendLongJumpScope suspend_long_jump_scope(thread);
         TransitionToGenerated transition(thread);
@@ -160,7 +160,7 @@
                                             arguments, thread);
       }
 
-      // No bytecode, fall back to compilation.
+      // Fall back to compilation.
     }
 
     const Object& result =
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 6e3bcc2..7ba428b 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -1060,41 +1060,18 @@
 
   ASSERT(!IsInterpreted());
   ASSERT(script.kind() == RawScript::kKernelTag);
-  const Array& await_to_token_map =
-      Array::Handle(zone, script.yield_positions());
-  if (await_to_token_map.IsNull()) {
-    // No mapping.
-    return;
-  }
   const intptr_t await_jump_var = GetAwaitJumpVariable();
   if (await_jump_var < 0) {
     return;
   }
   intptr_t await_to_token_map_index = await_jump_var - 1;
-  // yield_positions returns all yield positions for the script (in sorted
-  // order).
-  // We thus need to offset the function start to get the actual index.
-  if (!function_.token_pos().IsReal()) {
-    return;
-  }
-  const intptr_t function_start = function_.token_pos().value();
-  for (intptr_t i = 0;
-       i < await_to_token_map.Length() &&
-       Smi::Value(reinterpret_cast<RawSmi*>(await_to_token_map.At(i))) <
-           function_start;
-       i++) {
-    await_to_token_map_index++;
-  }
-
-  if (await_to_token_map_index >= await_to_token_map.Length()) {
-    return;
-  }
-
+  const auto& array =
+      GrowableObjectArray::Handle(zone, script.GetYieldPositions(function_));
+  // await_jump_var is non zero means that array should not be empty
+  // index also fall into the correct range
+  ASSERT(array.Length() > 0 && await_to_token_map_index < array.Length());
   const Object& token_pos =
-      Object::Handle(await_to_token_map.At(await_to_token_map_index));
-  if (token_pos.IsNull()) {
-    return;
-  }
+      Object::Handle(zone, array.At(await_to_token_map_index));
   ASSERT(token_pos.IsSmi());
   token_pos_ = TokenPosition(Smi::Cast(token_pos).Value());
   token_pos_initialized_ = true;
@@ -1156,7 +1133,8 @@
       } else if (obj.IsContext()) {
         ctx_ = Context::Cast(obj).raw();
       } else {
-        ASSERT(obj.IsNull());
+        ASSERT(obj.IsNull() || obj.raw() == Symbols::OptimizedOut().raw());
+        ctx_ = Context::null();
       }
       return ctx_;
     }
@@ -1431,7 +1409,12 @@
                                                   intptr_t ctx_slot,
                                                   intptr_t frame_ctx_level) {
   const Context& ctx = GetSavedCurrentContext();
-  ASSERT(!ctx.IsNull());
+
+  // It's possible that ctx was optimized out as no locals were captured by the
+  // context. See issue #38182.
+  if (ctx.IsNull()) {
+    return Symbols::OptimizedOut().raw();
+  }
 
   intptr_t level_diff = frame_ctx_level - var_ctx_level;
   if (level_diff == 0) {
@@ -1440,8 +1423,7 @@
     }
     ASSERT((ctx_slot >= 0) && (ctx_slot < ctx.num_variables()));
     return ctx.At(ctx_slot);
-  } else {
-    ASSERT(level_diff > 0);
+  } else if (level_diff > 0) {
     Context& var_ctx = Context::Handle(ctx.raw());
     while (level_diff > 0 && !var_ctx.IsNull()) {
       level_diff--;
@@ -1454,6 +1436,9 @@
     ASSERT(!var_ctx.IsNull());
     ASSERT((ctx_slot >= 0) && (ctx_slot < var_ctx.num_variables()));
     return var_ctx.At(ctx_slot);
+  } else {
+    PrintContextMismatchError(ctx_slot, frame_ctx_level, var_ctx_level);
+    return Object::null();
   }
 }
 
@@ -1607,7 +1592,7 @@
   }
   const String& url = String::Handle(SourceUrl());
   intptr_t line = LineNumber();
-  const char* func_name = Debugger::QualifiedFunctionName(function());
+  const char* func_name = function().ToFullyQualifiedCString();
   if (live_frame_) {
     return Thread::Current()->zone()->PrintToString(
         "[ Frame pc(0x%" Px " %s offset:0x%" Px ") fp(0x%" Px ") sp(0x%" Px
@@ -1802,6 +1787,7 @@
 #endif
 {
   ASSERT(!bytecode.IsNull());
+  ASSERT(FLAG_enable_interpreter);
   ASSERT(token_pos_.IsReal());
   ASSERT(pc_ != 0);
 }
@@ -3171,7 +3157,7 @@
   ASSERT(!func.HasOptimizedCode());
   ASSERT(func.HasCode() || func.HasBytecode());
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  if (func.HasBytecode()) {
+  if (func.HasBytecode() && FLAG_enable_interpreter) {
     Bytecode& bytecode = Bytecode::Handle(func.bytecode());
     ASSERT(!bytecode.IsNull());
     uword pc = 0;
@@ -3293,7 +3279,7 @@
         (function.end_token_pos() == end_pos) &&
         (function.script() == script.raw())) {
       if (function.is_debuggable()) {
-        if (function.HasBytecode()) {
+        if (FLAG_enable_interpreter && function.HasBytecode()) {
           bytecode_function_list->Add(function);
         }
         if (function.HasCode()) {
@@ -3303,7 +3289,7 @@
       if (function.HasImplicitClosureFunction()) {
         function = function.ImplicitClosureFunction();
         if (function.is_debuggable()) {
-          if (function.HasBytecode()) {
+          if (FLAG_enable_interpreter && function.HasBytecode()) {
             bytecode_function_list->Add(function);
           }
           if (function.HasCode()) {
@@ -3337,11 +3323,12 @@
           ASSERT(!function.IsNull());
           bool function_added = false;
           if (function.is_debuggable() &&
-              (function.HasCode() || function.HasBytecode()) &&
+              (function.HasCode() ||
+               (FLAG_enable_interpreter && function.HasBytecode())) &&
               function.token_pos() == start_pos &&
               function.end_token_pos() == end_pos &&
               function.script() == script.raw()) {
-            if (function.HasBytecode()) {
+            if (FLAG_enable_interpreter && function.HasBytecode()) {
               bytecode_function_list->Add(function);
             }
             if (function.HasCode()) {
@@ -3352,7 +3339,7 @@
           if (function_added && function.HasImplicitClosureFunction()) {
             function = function.ImplicitClosureFunction();
             if (function.is_debuggable()) {
-              if (function.HasBytecode()) {
+              if (FLAG_enable_interpreter && function.HasBytecode()) {
                 bytecode_function_list->Add(function);
               }
               if (function.HasCode()) {
@@ -3498,6 +3485,7 @@
     intptr_t requested_column,
     TokenPosition exact_token_pos,
     const GrowableObjectArray& functions) {
+  ASSERT(!in_bytecode || FLAG_enable_interpreter);
   Function& function = Function::Handle();
   function ^= functions.At(0);
   TokenPosition breakpoint_pos =
@@ -4398,12 +4386,16 @@
     ASSERT(!top_frame->IsInterpreted());
     const Script& script = Script::Handle(zone, top_frame->SourceScript());
     ASSERT(script.kind() == RawScript::kKernelTag);
-    // Are we at a yield point (previous await)?
-    const Array& yields = Array::Handle(script.yield_positions());
+    const auto& yield_positions = GrowableObjectArray::Handle(
+        zone, script.GetYieldPositions(top_frame->function()));
+    // No yield statements
+    if (yield_positions.IsNull() || (yield_positions.Length() == 0)) {
+      return false;
+    }
     intptr_t looking_for = top_frame->TokenPos().value();
     Smi& value = Smi::Handle(zone);
-    for (int i = 0; i < yields.Length(); i++) {
-      value ^= yields.At(i);
+    for (int i = 0; i < yield_positions.Length(); i++) {
+      value ^= yield_positions.At(i);
       if (value.Value() == looking_for) {
         return true;
       }
@@ -4722,6 +4714,10 @@
     // Return with minimal overhead if there are no breakpoints.
     return;
   }
+  if (bytecode_loaded && !FLAG_enable_interpreter) {
+    // We do not set breakpoints in bytecode if the interpreter is not used.
+    return;
+  }
   if (!func.is_debuggable()) {
     // Nothing to do if the function is not debuggable. If there is
     // a pending breakpoint in an inner function (that is debuggable),
diff --git a/runtime/vm/debugger_dbc.cc b/runtime/vm/debugger_dbc.cc
index c36dddb..56234ce 100644
--- a/runtime/vm/debugger_dbc.cc
+++ b/runtime/vm/debugger_dbc.cc
@@ -29,9 +29,11 @@
 
 void CodeBreakpoint::PatchCode() {
   ASSERT(!is_enabled_);
-  const Code& code = Code::Handle(code_);
-  const Instructions& instrs = Instructions::Handle(code.instructions());
-  {
+  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_) {
@@ -67,15 +69,17 @@
     } else {
       saved_value_fastsmi_ = SimulatorBytecode::kTrap;
     }
-  }
+  });
   is_enabled_ = true;
 }
 
 void CodeBreakpoint::RestoreCode() {
   ASSERT(is_enabled_);
-  const Code& code = Code::Handle(code_);
-  const Instructions& instrs = Instructions::Handle(code.instructions());
-  {
+  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:
@@ -94,7 +98,7 @@
              SimulatorBytecode::kNop);
       *FastSmiInstructionFromReturnAddress(pc_) = saved_value_fastsmi_;
     }
-  }
+  });
   is_enabled_ = false;
 }
 
diff --git a/runtime/vm/debugger_ia32.cc b/runtime/vm/debugger_ia32.cc
index 10ee78f..8b1eb8a 100644
--- a/runtime/vm/debugger_ia32.cc
+++ b/runtime/vm/debugger_ia32.cc
@@ -25,10 +25,12 @@
 
 void CodeBreakpoint::PatchCode() {
   ASSERT(!is_enabled_);
-  const Code& code = Code::Handle(code_);
-  const Instructions& instrs = Instructions::Handle(code.instructions());
-  Code& stub_target = Code::Handle();
-  {
+  auto thread = Thread::Current();
+  auto zone = thread->zone();
+  const Code& code = Code::Handle(zone, code_);
+  const Instructions& instrs = Instructions::Handle(zone, code.instructions());
+  Code& stub_target = Code::Handle(zone);
+  thread->isolate_group()->RunWithStoppedMutators([&]() {
     WritableInstructionsScope writable(instrs.PayloadStart(), instrs.Size());
     switch (breakpoint_kind_) {
       case RawPcDescriptors::kIcCall: {
@@ -49,15 +51,17 @@
     }
     saved_value_ = CodePatcher::GetStaticCallTargetAt(pc_, code);
     CodePatcher::PatchStaticCallAt(pc_, code, stub_target);
-  }
+  });
   is_enabled_ = true;
 }
 
 void CodeBreakpoint::RestoreCode() {
   ASSERT(is_enabled_);
-  const Code& code = Code::Handle(code_);
-  const Instructions& instrs = Instructions::Handle(code.instructions());
-  {
+  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:
@@ -69,7 +73,7 @@
       default:
         UNREACHABLE();
     }
-  }
+  });
   is_enabled_ = false;
 }
 
diff --git a/runtime/vm/growable_array_test.cc b/runtime/vm/growable_array_test.cc
index 2b9b23b..7c0ee5d 100644
--- a/runtime/vm/growable_array_test.cc
+++ b/runtime/vm/growable_array_test.cc
@@ -107,4 +107,35 @@
   EXPECT_EQ(1, test2->length());
 }
 
+TEST_CASE(GrowableArrayMoveCtor) {
+  GrowableArray<int> a;
+  a.Add(4);
+  a.Add(5);
+  int* a_data = a.data();
+
+  GrowableArray<int> b(std::move(a));
+
+  EXPECT_EQ(0, a.length());
+  EXPECT_EQ((int*)nullptr, a.data());
+  EXPECT_EQ(2, b.length());
+  EXPECT_EQ(a_data, b.data());
+}
+
+TEST_CASE(GrowableArrayMoveAssign) {
+  GrowableArray<int> a, b;
+  a.Add(1);
+  a.Add(2);
+  a.Add(3);
+  b.Add(7);
+  int* a_data = a.data();
+  int* b_data = b.data();
+
+  a = std::move(b);
+
+  EXPECT_EQ(1, a.length());
+  EXPECT_EQ(b_data, a.data());
+  EXPECT_EQ(3, b.length());
+  EXPECT_EQ(a_data, b.data());
+}
+
 }  // namespace dart
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index c097744..bd6f62b 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -219,7 +219,7 @@
 }
 
 static constexpr intptr_t kSimarmX64InstructionsAlignment =
-    2 * compiler::target::ObjectAlignment::kObjectAlignment;
+    compiler::target::ObjectAlignment::kObjectAlignment;
 static intptr_t InstructionsSizeInSnapshot(intptr_t len) {
   const intptr_t header_size = Utils::RoundUp(3 * compiler::target::kWordSize,
                                               kSimarmX64InstructionsAlignment);
@@ -738,7 +738,7 @@
       uword next_reloc_offset = iterator.MoveNext() ? iterator.PcOffset() : -1;
 
       for (uword cursor = entry; cursor < end;
-           cursor += sizeof(compiler::target::uword*)) {
+           cursor += sizeof(compiler::target::uword)) {
         compiler::target::uword data =
             *reinterpret_cast<compiler::target::uword*>(cursor);
         if ((cursor - entry) == next_reloc_offset) {
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index e4a735a..a46aa0f 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -535,9 +535,10 @@
 // Calling into runtime may trigger garbage collection and relocate objects,
 // so all RawObject* pointers become outdated and should not be used across
 // runtime calls.
-// Note: functions below are marked DART_NOINLINE to recover performance on
-// ARM where inlining these functions into the interpreter loop seemed to cause
-// some code quality issues.
+// 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.
 static DART_NOINLINE bool InvokeRuntime(Thread* thread,
                                         Interpreter* interpreter,
                                         RuntimeFunction drt,
@@ -725,50 +726,6 @@
   }
 }
 
-void Interpreter::InlineCacheMiss(int checked_args,
-                                  Thread* thread,
-                                  RawICData* icdata,
-                                  RawObject** args,
-                                  RawObject** top,
-                                  const KBCInstr* 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;
-  Exit(thread, FP, exit_frame, pc);
-  NativeArguments native_args(thread, miss_handler_argc, miss_handler_args,
-                              result);
-  handler(native_args);
-
-  argdesc_ = Array::RawCast(top[1]);
-}
-
 DART_FORCE_INLINE bool Interpreter::InstanceCall(Thread* thread,
                                                  RawString* target_name,
                                                  RawObject** call_base,
@@ -1058,8 +1015,8 @@
       SP[1] = 0; /* Unused result. */                                          \
       SP[2] = function;                                                        \
       Exit(thread, FP, SP + 3, pc);                                            \
-      NativeArguments native_args(thread, 1, SP + 2, SP + 1);                  \
-      INVOKE_RUNTIME(DRT_CompileInterpretedFunction, native_args);             \
+      INVOKE_RUNTIME(DRT_CompileInterpretedFunction,                           \
+                     NativeArguments(thread, 1, SP + 2, SP + 1));              \
       function = FrameFunction(FP);                                            \
     }                                                                          \
   }
@@ -1075,14 +1032,14 @@
     if (thread->isolate()->debugger()->HasBytecodeBreakpointAt(pc)) {          \
       SP[1] = null_value;                                                      \
       Exit(thread, FP, SP + 2, pc);                                            \
-      NativeArguments args(thread, 0, NULL, SP + 1);                           \
-      INVOKE_RUNTIME(DRT_BreakpointRuntimeHandler, args)                       \
+      INVOKE_RUNTIME(DRT_BreakpointRuntimeHandler,                             \
+                     NativeArguments(thread, 0, nullptr, SP + 1))              \
     }                                                                          \
     /* The debugger expects to see the same pc again when single-stepping */   \
     if (thread->isolate()->single_step()) {                                    \
       Exit(thread, FP, SP + 1, pc);                                            \
-      NativeArguments args(thread, 0, NULL, NULL);                             \
-      INVOKE_RUNTIME(DRT_SingleStepHandler, args);                             \
+      INVOKE_RUNTIME(DRT_SingleStepHandler,                                    \
+                     NativeArguments(thread, 0, nullptr, nullptr));            \
     }                                                                          \
   }
 #endif  // PRODUCT
@@ -1679,8 +1636,8 @@
       if (reinterpret_cast<uword>(SP) >= overflow_stack_limit() ||
           thread->HasScheduledInterrupts()) {
         Exit(thread, FP, SP + 1, pc);
-        NativeArguments args(thread, 0, NULL, NULL);
-        INVOKE_RUNTIME(DRT_StackOverflow, args);
+        INVOKE_RUNTIME(DRT_StackOverflow,
+                       NativeArguments(thread, 0, nullptr, nullptr));
       }
     }
     RawFunction* function = FrameFunction(FP);
@@ -1691,8 +1648,8 @@
       SP[1] = 0;  // Unused result.
       SP[2] = function;
       Exit(thread, FP, SP + 3, pc);
-      NativeArguments native_args(thread, 1, SP + 2, SP + 1);
-      INVOKE_RUNTIME(DRT_CompileInterpretedFunction, native_args);
+      INVOKE_RUNTIME(DRT_CompileInterpretedFunction,
+                     NativeArguments(thread, 1, SP + 2, SP + 1));
     }
     DISPATCH();
   }
@@ -1734,8 +1691,8 @@
     SP[3] = SP[0];
     Exit(thread, FP, SP + 4, pc);
     {
-      NativeArguments args(thread, 3, SP + 1, SP - 1);
-      INVOKE_RUNTIME(DRT_InstantiateType, args);
+      INVOKE_RUNTIME(DRT_InstantiateType,
+                     NativeArguments(thread, 3, SP + 1, SP - 1));
     }
     SP -= 1;
     DISPATCH();
@@ -1773,8 +1730,8 @@
       SP[3] = function_type_args;
 
       Exit(thread, FP, SP + 4, pc);
-      NativeArguments args(thread, 3, SP + 1, SP - 1);
-      INVOKE_RUNTIME(DRT_InstantiateTypeArguments, args);
+      INVOKE_RUNTIME(DRT_InstantiateTypeArguments,
+                     NativeArguments(thread, 3, SP + 1, SP - 1));
     }
 
   InstantiateTypeArgumentsTOSDone:
@@ -1788,11 +1745,9 @@
       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);
+        INVOKE_RUNTIME(DRT_Throw, NativeArguments(thread, 1, SP, SP + 1));
       } else {  // ReThrow
-        NativeArguments args(thread, 2, SP - 1, SP + 1);
-        INVOKE_RUNTIME(DRT_ReThrow, args);
+        INVOKE_RUNTIME(DRT_ReThrow, NativeArguments(thread, 2, SP - 1, SP + 1));
       }
     }
     DISPATCH();
@@ -2190,11 +2145,12 @@
         RawObject** incoming_args = SP - num_arguments;
         RawObject** return_slot = SP;
         Exit(thread, FP, SP + 1, pc);
-        NativeArguments args(thread, argc_tag, incoming_args, return_slot);
+        NativeArguments native_args(thread, argc_tag, incoming_args,
+                                    return_slot);
         INVOKE_NATIVE(
             payload->trampoline,
             reinterpret_cast<Dart_NativeFunction>(payload->native_function),
-            reinterpret_cast<Dart_NativeArguments>(&args));
+            reinterpret_cast<Dart_NativeArguments>(&native_args));
 
         *(SP - num_arguments) = *return_slot;
         SP -= num_arguments;
@@ -2305,8 +2261,9 @@
       SP[2] = field;
       SP[3] = value;
       Exit(thread, FP, SP + 4, pc);
-      NativeArguments args(thread, 2, /* argv */ SP + 2, /* retval */ SP + 1);
-      if (!InvokeRuntime(thread, this, DRT_UpdateFieldCid, args)) {
+      if (!InvokeRuntime(thread, this, DRT_UpdateFieldCid,
+                         NativeArguments(thread, 2, /* argv */ SP + 2,
+                                         /* retval */ SP + 1))) {
         HANDLE_EXCEPTION;
       }
 
@@ -2462,8 +2419,7 @@
     {
       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);
+      INVOKE_RUNTIME(DRT_CloneContext, NativeArguments(thread, 1, SP + 1, SP));
     }
     DISPATCH();
   }
@@ -2491,8 +2447,8 @@
     SP[2] = cls;         // 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);
+    INVOKE_RUNTIME(DRT_AllocateObject,
+                   NativeArguments(thread, 2, SP + 2, SP + 1));
     SP++;  // Result is in SP[1].
     DISPATCH();
   }
@@ -2523,8 +2479,8 @@
     SP[1] = cls;
     SP[2] = type_args;
     Exit(thread, FP, SP + 3, pc);
-    NativeArguments args(thread, 2, SP + 1, SP - 1);
-    INVOKE_RUNTIME(DRT_AllocateObject, args);
+    INVOKE_RUNTIME(DRT_AllocateObject,
+                   NativeArguments(thread, 2, SP + 1, SP - 1));
     SP -= 1;  // Result is in SP - 1.
     DISPATCH();
   }
@@ -2579,8 +2535,8 @@
     RawObject** result_slot = SP;
 
     Exit(thread, FP, SP + 1, pc);
-    NativeArguments native_args(thread, 5, args, result_slot);
-    INVOKE_RUNTIME(DRT_SubtypeCheck, native_args);
+    INVOKE_RUNTIME(DRT_SubtypeCheck,
+                   NativeArguments(thread, 5, args, result_slot));
 
     // Result slot not used anymore.
     SP--;
@@ -2606,8 +2562,8 @@
     {
       SP[1] = SP[0];  // instance
       Exit(thread, FP, SP + 2, pc);
-      NativeArguments args(thread, 1, SP + 1, SP);
-      INVOKE_RUNTIME(DRT_NonBoolTypeError, args);
+      INVOKE_RUNTIME(DRT_NonBoolTypeError,
+                     NativeArguments(thread, 1, SP + 1, SP));
     }
 
   AssertBooleanOk:
@@ -3146,10 +3102,9 @@
         SP[1] = null_value;  // Result.
 
         Exit(thread, FP, SP + 2, pc);
-        NativeArguments native_args(thread, 0, /* argv */ SP + 1,
-                                    /* retval */ SP + 1);
         if (!InvokeRuntime(thread, this, DRT_AllocateSubtypeTestCache,
-                           native_args)) {
+                           NativeArguments(thread, 0, /* argv */ SP + 1,
+                                           /* retval */ SP + 1))) {
           HANDLE_EXCEPTION;
         }
 
@@ -3185,9 +3140,9 @@
       SP[2] = field;
       SP[3] = value;
       Exit(thread, FP, SP + 4, pc);
-      NativeArguments native_args(thread, 2, /* argv */ SP + 2,
-                                  /* retval */ SP + 1);
-      if (!InvokeRuntime(thread, this, DRT_UpdateFieldCid, native_args)) {
+      if (!InvokeRuntime(thread, this, DRT_UpdateFieldCid,
+                         NativeArguments(thread, 2, /* argv */ SP + 2,
+                                         /* retval */ SP + 1))) {
         HANDLE_EXCEPTION;
       }
 
@@ -3250,8 +3205,8 @@
       SP[1] = 0;  // Unused result of invoking the initializer.
       SP[2] = field;
       Exit(thread, FP, SP + 3, pc);
-      NativeArguments native_args(thread, 1, SP + 2, SP + 1);
-      INVOKE_RUNTIME(DRT_InitStaticField, native_args);
+      INVOKE_RUNTIME(DRT_InitStaticField,
+                     NativeArguments(thread, 1, SP + 2, SP + 1));
 
       // Reload objects after the call which may trigger GC.
       function = FrameFunction(FP);
@@ -3351,8 +3306,8 @@
       SP[3] = receiver;                // Receiver.
       SP[4] = function->ptr()->name_;  // Field name.
       Exit(thread, FP, SP + 5, pc);
-      NativeArguments native_args(thread, 2, SP + 3, SP + 2);
-      if (!InvokeRuntime(thread, this, DRT_GetFieldForDispatch, native_args)) {
+      if (!InvokeRuntime(thread, this, DRT_GetFieldForDispatch,
+                         NativeArguments(thread, 2, SP + 3, SP + 2))) {
         HANDLE_EXCEPTION;
       }
       argdesc_ = Array::RawCast(SP[1]);
@@ -3374,8 +3329,8 @@
       SP[2] = receiver;
       SP[3] = argdesc_;
       Exit(thread, FP, SP + 4, pc);
-      NativeArguments native_args(thread, 2, SP + 2, SP + 1);
-      if (!InvokeRuntime(thread, this, DRT_ResolveCallFunction, native_args)) {
+      if (!InvokeRuntime(thread, this, DRT_ResolveCallFunction,
+                         NativeArguments(thread, 2, SP + 2, SP + 1))) {
         HANDLE_EXCEPTION;
       }
       argdesc_ = Array::RawCast(SP[3]);
@@ -3401,8 +3356,8 @@
       SP[5] = Smi::New(argc);  // length
       SP[6] = null_value;      // type
       Exit(thread, FP, SP + 7, pc);
-      NativeArguments native_args(thread, 2, SP + 5, SP + 4);
-      if (!InvokeRuntime(thread, this, DRT_AllocateArray, native_args)) {
+      if (!InvokeRuntime(thread, this, DRT_AllocateArray,
+                         NativeArguments(thread, 2, SP + 5, SP + 4))) {
         HANDLE_EXCEPTION;
       }
     }
@@ -3422,8 +3377,8 @@
     // array of arguments, and target name.
     {
       Exit(thread, FP, SP + 6, pc);
-      NativeArguments native_args(thread, 4, SP + 2, SP + 1);
-      if (!InvokeRuntime(thread, this, DRT_InvokeNoSuchMethod, native_args)) {
+      if (!InvokeRuntime(thread, this, DRT_InvokeNoSuchMethod,
+                         NativeArguments(thread, 4, SP + 2, SP + 1))) {
         HANDLE_EXCEPTION;
       }
 
@@ -3484,8 +3439,8 @@
         SP[8] = SP[5];       // instantiator_type_args
         SP[9] = null_value;  // function_type_args
         Exit(thread, FP, SP + 10, pc);
-        NativeArguments args(thread, 3, SP + 7, SP + 7);
-        INVOKE_RUNTIME(DRT_InstantiateTypeArguments, args);
+        INVOKE_RUNTIME(DRT_InstantiateTypeArguments,
+                       NativeArguments(thread, 3, SP + 7, SP + 7));
         SP[6] = SP[7];
       }
     }
@@ -3518,8 +3473,8 @@
         SP[9] = check->ptr()->name_;
         SP[10] = 0;
         Exit(thread, FP, SP + 11, pc);
-        NativeArguments native_args(thread, 5, SP + 5, SP + 10);
-        INVOKE_RUNTIME(DRT_SubtypeCheck, native_args);
+        INVOKE_RUNTIME(DRT_SubtypeCheck,
+                       NativeArguments(thread, 5, SP + 5, SP + 10));
       }
 
       checks = Array::RawCast(SP[1]);  // Reload after runtime call.
@@ -3602,9 +3557,9 @@
       SP[2] = 0;  // Code result.
       SP[3] = function;
       Exit(thread, FP, SP + 4, pc);
-      NativeArguments native_args(thread, 1, /* argv */ SP + 3,
-                                  /* retval */ SP + 2);
-      if (!InvokeRuntime(thread, this, DRT_CompileFunction, native_args)) {
+      if (!InvokeRuntime(thread, this, DRT_CompileFunction,
+                         NativeArguments(thread, 1, /* argv */ SP + 3,
+                                         /* retval */ SP + 2))) {
         HANDLE_EXCEPTION;
       }
       function = Function::RawCast(SP[3]);
@@ -3637,8 +3592,8 @@
       SP[6] = Smi::New(argc);  // length
       SP[7] = null_value;      // type
       Exit(thread, FP, SP + 8, pc);
-      NativeArguments native_args(thread, 2, SP + 6, SP + 5);
-      if (!InvokeRuntime(thread, this, DRT_AllocateArray, native_args)) {
+      if (!InvokeRuntime(thread, this, DRT_AllocateArray,
+                         NativeArguments(thread, 2, SP + 6, SP + 5))) {
         HANDLE_EXCEPTION;
       }
 
@@ -3654,8 +3609,8 @@
     // and array of arguments.
     {
       Exit(thread, FP, SP + 6, pc);
-      NativeArguments native_args(thread, 4, SP + 2, SP + 1);
-      INVOKE_RUNTIME(DRT_NoSuchMethodFromPrologue, native_args);
+      INVOKE_RUNTIME(DRT_NoSuchMethodFromPrologue,
+                     NativeArguments(thread, 4, SP + 2, SP + 1));
       ++SP;  // Result at SP[0]
     }
 
@@ -3667,8 +3622,8 @@
     // SP[0] contains selector.
     SP[1] = 0;  // Unused space for result.
     Exit(thread, FP, SP + 2, pc);
-    NativeArguments args(thread, 1, SP, SP + 1);
-    INVOKE_RUNTIME(DRT_NullErrorWithSelector, args);
+    INVOKE_RUNTIME(DRT_NullErrorWithSelector,
+                   NativeArguments(thread, 1, SP, SP + 1));
     UNREACHABLE();
   }
 
@@ -3676,8 +3631,8 @@
   ThrowIntegerDivisionByZeroException:
     SP[0] = 0;  // Unused space for result.
     Exit(thread, FP, SP + 1, pc);
-    NativeArguments args(thread, 0, SP, SP);
-    INVOKE_RUNTIME(DRT_IntegerDivisionByZeroException, args);
+    INVOKE_RUNTIME(DRT_IntegerDivisionByZeroException,
+                   NativeArguments(thread, 0, SP, SP));
     UNREACHABLE();
   }
 
@@ -3686,8 +3641,7 @@
     // SP[0] contains value.
     SP[1] = 0;  // Unused space for result.
     Exit(thread, FP, SP + 2, pc);
-    NativeArguments args(thread, 1, SP, SP + 1);
-    INVOKE_RUNTIME(DRT_ArgumentError, args);
+    INVOKE_RUNTIME(DRT_ArgumentError, NativeArguments(thread, 1, SP, SP + 1));
     UNREACHABLE();
   }
 
diff --git a/runtime/vm/interpreter.h b/runtime/vm/interpreter.h
index 4889a5a..e7fa7d6 100644
--- a/runtime/vm/interpreter.h
+++ b/runtime/vm/interpreter.h
@@ -176,15 +176,6 @@
                       RawObject*** FP,
                       RawObject*** SP);
 
-  void InlineCacheMiss(int checked_args,
-                       Thread* thread,
-                       RawICData* icdata,
-                       RawObject** call_base,
-                       RawObject** top,
-                       const KBCInstr* pc,
-                       RawObject** FP,
-                       RawObject** SP);
-
   bool InstanceCall(Thread* thread,
                     RawString* target_name,
                     RawObject** call_base,
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 261fde1..fc85292 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -132,17 +132,17 @@
 
 IsolateGroup::IsolateGroup(std::unique_ptr<IsolateGroupSource> source,
                            void* embedder_data)
-    : source_(std::move(source)),
-      embedder_data_(embedder_data),
+    : embedder_data_(embedder_data),
+      isolates_rwlock_(new RwLock()),
+      isolates_(),
+      source_(std::move(source)),
       thread_registry_(new ThreadRegistry()),
-      safepoint_handler_(new SafepointHandler(this)),
-      isolates_monitor_(new Monitor()),
-      isolates_() {}
+      safepoint_handler_(new SafepointHandler(this)) {}
 
 IsolateGroup::~IsolateGroup() {}
 
 void IsolateGroup::RegisterIsolate(Isolate* isolate) {
-  MonitorLocker ml(isolates_monitor_.get());
+  WriteRwLocker wl(ThreadState::Current(), isolates_rwlock_.get());
   isolates_.Append(isolate);
   isolate_count_++;
 }
@@ -150,7 +150,7 @@
 void IsolateGroup::UnregisterIsolate(Isolate* isolate) {
   bool is_last_isolate = false;
   {
-    MonitorLocker ml(isolates_monitor_.get());
+    WriteRwLocker wl(ThreadState::Current(), isolates_rwlock_.get());
     isolates_.Remove(isolate);
     isolate_count_--;
     is_last_isolate = isolate_count_ == 0;
@@ -2226,6 +2226,30 @@
   ASSERT(!Thread::Current()->is_marking());
 }
 
+void IsolateGroup::RunWithStoppedMutators(
+    std::function<void()> single_current_mutator,
+    std::function<void()> otherwise,
+    bool use_force_growth_in_otherwise) {
+  auto thread = Thread::Current();
+
+  ReadRwLocker wl(thread, isolates_rwlock_.get());
+  const bool only_one_isolate = isolates_.First() == isolates_.Last();
+  if (thread->IsMutatorThread() && only_one_isolate) {
+    single_current_mutator();
+  } else {
+    // We use the more strict safepoint operation scope here (which ensures that
+    // all other threads, including auxiliary threads are at a safepoint), even
+    // though we only need to ensure that the mutator threads are stopped.
+    if (use_force_growth_in_otherwise) {
+      ForceGrowthSafepointOperationScope safepoint_scope(thread);
+      otherwise();
+    } else {
+      SafepointOperationScope safepoint_scope(thread);
+      otherwise();
+    }
+  }
+}
+
 RawClass* Isolate::GetClassForHeapWalkAt(intptr_t cid) {
   RawClass* raw_class = nullptr;
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index faef0b3..701d58f 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -9,6 +9,7 @@
 #error "Should not include runtime"
 #endif
 
+#include <functional>
 #include <memory>
 #include <utility>
 
@@ -78,6 +79,7 @@
 class RawInt32x4;
 class RawUserTag;
 class ReversePcLookupCache;
+class RwLock;
 class SafepointHandler;
 class SampleBuffer;
 class SendPort;
@@ -262,16 +264,36 @@
     library_tag_handler_ = handler;
   }
 
+  // Ensures mutators are stopped during execution of the provided function.
+  //
+  // If the current thread is the only mutator in the isolate group,
+  // [single_current_mutator] will be called. Otherwise [otherwise] will be
+  // called inside a [SafepointOperationsScope] (or
+  // [ForceGrowthSafepointOperationScope] if [use_force_growth_in_otherwise]
+  // is set).
+  //
+  // During the duration of this function, no new isolates can be added to the
+  // isolate group.
+  void RunWithStoppedMutators(std::function<void()> single_current_mutator,
+                              std::function<void()> otherwise,
+                              bool use_force_growth_in_otherwise = false);
+
+  void RunWithStoppedMutators(std::function<void()> function) {
+    RunWithStoppedMutators(function, function);
+  }
+
  private:
-  std::unique_ptr<IsolateGroupSource> source_;
   void* embedder_data_ = nullptr;
-  std::unique_ptr<ThreadRegistry> thread_registry_;
-  std::unique_ptr<SafepointHandler> safepoint_handler_;
-  std::unique_ptr<Monitor> isolates_monitor_;
+
+  std::unique_ptr<RwLock> isolates_rwlock_;
   IntrusiveDList<Isolate> isolates_;
   intptr_t isolate_count_ = 0;
   bool initial_spawn_successful_ = false;
   Dart_LibraryTagHandler library_tag_handler_ = nullptr;
+
+  std::unique_ptr<IsolateGroupSource> source_;
+  std::unique_ptr<ThreadRegistry> thread_registry_;
+  std::unique_ptr<SafepointHandler> safepoint_handler_;
 };
 
 class Isolate : public BaseIsolate, public IntrusiveDListEntry<Isolate> {
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index 9e6af12..2b82f32 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -8,6 +8,7 @@
 #include "vm/compiler/frontend/bytecode_reader.h"
 #include "vm/compiler/frontend/constant_evaluator.h"
 #include "vm/compiler/frontend/kernel_translation_helper.h"
+#include "vm/compiler/jit/compiler.h"
 #include "vm/longjump.h"
 #include "vm/object_store.h"
 #include "vm/parser.h"  // For Parser::kParameter* constants.
@@ -134,8 +135,7 @@
       intptr_t data_program_offset,
       intptr_t initial_script_index,
       intptr_t record_for_script_id,
-      GrowableArray<intptr_t>* record_token_positions_into,
-      GrowableArray<intptr_t>* record_yield_positions_into)
+      GrowableArray<intptr_t>* record_token_positions_into)
       : KernelReaderHelper(zone,
                            translation_helper,
                            script,
@@ -143,13 +143,11 @@
                            data_program_offset),
         current_script_id_(initial_script_index),
         record_for_script_id_(record_for_script_id),
-        record_token_positions_into_(record_token_positions_into),
-        record_yield_positions_into_(record_yield_positions_into) {}
+        record_token_positions_into_(record_token_positions_into) {}
 
   void CollectTokenPositions(intptr_t kernel_offset);
 
   void RecordTokenPosition(TokenPosition position) override;
-  void RecordYieldPosition(TokenPosition position) override;
 
   void set_current_script_id(intptr_t id) override { current_script_id_ = id; }
 
@@ -157,7 +155,6 @@
   intptr_t current_script_id_;
   intptr_t record_for_script_id_;
   GrowableArray<intptr_t>* record_token_positions_into_;
-  GrowableArray<intptr_t>* record_yield_positions_into_;
 
   DISALLOW_COPY_AND_ASSIGN(KernelTokenPositionCollector);
 };
@@ -195,13 +192,6 @@
   }
 }
 
-void KernelTokenPositionCollector::RecordYieldPosition(TokenPosition position) {
-  if (record_for_script_id_ == current_script_id_ &&
-      record_yield_positions_into_ != NULL && position.IsReal()) {
-    record_yield_positions_into_->Add(position.value());
-  }
-}
-
 static int LowestFirst(const intptr_t* a, const intptr_t* b) {
   return *a - *b;
 }
@@ -246,8 +236,7 @@
     intptr_t data_kernel_offset,
     Zone* zone,
     TranslationHelper* helper,
-    GrowableArray<intptr_t>* token_positions,
-    GrowableArray<intptr_t>* yield_positions) {
+    GrowableArray<intptr_t>* token_positions) {
   if (kernel_data.IsNull()) {
     return;
   }
@@ -255,7 +244,7 @@
   KernelTokenPositionCollector token_position_collector(
       zone, helper, script, kernel_data, data_kernel_offset,
       entry_script.kernel_script_index(), script.kernel_script_index(),
-      token_positions, yield_positions);
+      token_positions);
 
   token_position_collector.CollectTokenPositions(kernel_offset);
 }
@@ -333,7 +322,6 @@
   helper.InitFromScript(interesting_script);
 
   GrowableArray<intptr_t> token_positions(10);
-  GrowableArray<intptr_t> yield_positions(1);
 
   Isolate* isolate = thread->isolate();
   const GrowableObjectArray& libs =
@@ -396,7 +384,7 @@
                   data, interesting_script, entry_script,
                   temp_field.kernel_offset(),
                   temp_field.KernelDataProgramOffset(), zone, &helper,
-                  &token_positions, &yield_positions);
+                  &token_positions);
             }
           }
           temp_array = klass.functions();
@@ -415,7 +403,7 @@
                   data, interesting_script, entry_script,
                   temp_function.kernel_offset(),
                   temp_function.KernelDataProgramOffset(), zone, &helper,
-                  &token_positions, &yield_positions);
+                  &token_positions);
             }
           }
         } else {
@@ -432,10 +420,9 @@
           if (entry_script.raw() != interesting_script.raw()) {
             continue;
           }
-          CollectKernelDataTokenPositions(data, interesting_script,
-                                          entry_script, class_offset,
-                                          library_kernel_offset, zone, &helper,
-                                          &token_positions, &yield_positions);
+          CollectKernelDataTokenPositions(
+              data, interesting_script, entry_script, class_offset,
+              library_kernel_offset, zone, &helper, &token_positions);
         }
       } else if (entry.IsFunction()) {
         temp_function ^= entry.raw();
@@ -452,7 +439,7 @@
               data, interesting_script, entry_script,
               temp_function.kernel_offset(),
               temp_function.KernelDataProgramOffset(), zone, &helper,
-              &token_positions, &yield_positions);
+              &token_positions);
         }
       } else if (entry.IsField()) {
         const Field& field = Field::Cast(entry);
@@ -476,8 +463,7 @@
           data = field.KernelData();
           CollectKernelDataTokenPositions(
               data, interesting_script, entry_script, field.kernel_offset(),
-              field.KernelDataProgramOffset(), zone, &helper, &token_positions,
-              &yield_positions);
+              field.KernelDataProgramOffset(), zone, &helper, &token_positions);
         }
       }
     }
@@ -487,10 +473,6 @@
   Array& array_object = Array::Handle(zone);
   array_object = AsSortedDuplicateFreeArray(&token_positions);
   script.set_debug_positions(array_object);
-  array_object = AsSortedDuplicateFreeArray(&yield_positions);
-  // Note that yield positions in members declared in bytecode are not collected
-  // here, but on demand in the debugger.
-  script.set_yield_positions(array_object);
 }
 
 class MetadataEvaluator : public KernelReaderHelper {
@@ -589,7 +571,7 @@
         type_translator_(this, active_class, /* finalize= */ true),
         constant_evaluator_(this, &type_translator_, active_class, nullptr) {}
 
-  RawObject* BuildParameterDescriptor(intptr_t kernel_offset);
+  RawObject* BuildParameterDescriptor(const Function& function);
 
  private:
   TypeTranslator type_translator_;
@@ -599,8 +581,8 @@
 };
 
 RawObject* ParameterDescriptorBuilder::BuildParameterDescriptor(
-    intptr_t kernel_offset) {
-  SetOffset(kernel_offset);
+    const Function& function) {
+  SetOffset(function.kernel_offset());
   ReadUntilFunctionNode();
   FunctionNodeHelper function_node_helper(this);
   function_node_helper.ReadUntilExcluding(
@@ -628,17 +610,19 @@
                            helper.IsFinal() ? Bool::True() : Bool::False());
 
     Tag tag = ReadTag();  // read (first part of) initializer.
-    if (tag == kSomething) {
+    if ((tag == kSomething) && !function.is_abstract()) {
       // this will (potentially) read the initializer, but reset the position.
       Instance& constant = Instance::ZoneHandle(
           zone_, constant_evaluator_.EvaluateExpression(ReaderOffset()));
-      SkipExpression();  // read (actual) initializer.
       param_descriptor.SetAt(entry_start + Parser::kParameterDefaultValueOffset,
                              constant);
     } else {
       param_descriptor.SetAt(entry_start + Parser::kParameterDefaultValueOffset,
                              Object::null_instance());
     }
+    if (tag == kSomething) {
+      SkipExpression();  // read (actual) initializer.
+    }
 
     if (FLAG_enable_mirrors && (helper.annotation_count_ > 0)) {
       AlternativeReadingScope alt(&reader_, param_kernel_offset);
@@ -683,7 +667,7 @@
         ExternalTypedData::Handle(zone, function.KernelData()),
         function.KernelDataProgramOffset(), &active_class);
 
-    return builder.BuildParameterDescriptor(function.kernel_offset());
+    return builder.BuildParameterDescriptor(function);
   } else {
     return Thread::Current()->StealStickyError();
   }
@@ -818,6 +802,10 @@
 
 ProcedureAttributesMetadata ProcedureAttributesOf(const Function& function,
                                                   Zone* zone) {
+  if (function.is_declared_in_bytecode()) {
+    // TODO(alexmarkov): add AOT metadata to bytecode.
+    return ProcedureAttributesMetadata();
+  }
   const Script& script = Script::Handle(zone, function.script());
   return ProcedureAttributesOf(
       zone, script, ExternalTypedData::Handle(zone, function.KernelData()),
@@ -826,6 +814,10 @@
 
 ProcedureAttributesMetadata ProcedureAttributesOf(const Field& field,
                                                   Zone* zone) {
+  if (field.is_declared_in_bytecode()) {
+    // TODO(alexmarkov): add AOT metadata to bytecode.
+    return ProcedureAttributesMetadata();
+  }
   const Class& parent = Class::Handle(zone, field.Owner());
   const Script& script = Script::Handle(zone, parent.script());
   return ProcedureAttributesOf(
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 009cab2..427163e 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 = 31;
+static const uint32_t kMaxSupportedKernelFormatVersion = 32;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
 #define KERNEL_TAG_LIST(V)                                                     \
@@ -407,36 +407,43 @@
 class AlternativeReadingScope {
  public:
   AlternativeReadingScope(Reader* reader, intptr_t new_position)
-      : reader_(reader),
-        saved_size_(reader_->size()),
-        saved_raw_buffer_(reader_->raw_buffer()),
-        saved_typed_data_(reader_->typed_data()),
-        saved_offset_(reader_->offset()) {
+      : reader_(reader), saved_offset_(reader_->offset()) {
     reader_->set_offset(new_position);
   }
 
-  AlternativeReadingScope(Reader* reader,
-                          const ExternalTypedData* new_typed_data,
-                          intptr_t new_position)
+  explicit AlternativeReadingScope(Reader* reader)
+      : reader_(reader), saved_offset_(reader_->offset()) {}
+
+  ~AlternativeReadingScope() { reader_->set_offset(saved_offset_); }
+
+  intptr_t saved_offset() { return saved_offset_; }
+
+ private:
+  Reader* const reader_;
+  const intptr_t saved_offset_;
+
+  DISALLOW_COPY_AND_ASSIGN(AlternativeReadingScope);
+};
+
+// Similar to AlternativeReadingScope, but also switches reading to another
+// typed data array.
+class AlternativeReadingScopeWithNewData {
+ public:
+  AlternativeReadingScopeWithNewData(Reader* reader,
+                                     const ExternalTypedData* new_typed_data,
+                                     intptr_t new_position)
       : reader_(reader),
         saved_size_(reader_->size()),
         saved_raw_buffer_(reader_->raw_buffer()),
         saved_typed_data_(reader_->typed_data()),
         saved_offset_(reader_->offset()) {
-    reader_->set_raw_buffer(NULL);
+    reader_->set_raw_buffer(nullptr);
     reader_->set_typed_data(new_typed_data);
     reader_->set_size(new_typed_data->Length());
     reader_->set_offset(new_position);
   }
 
-  explicit AlternativeReadingScope(Reader* reader)
-      : reader_(reader),
-        saved_size_(reader_->size()),
-        saved_raw_buffer_(reader_->raw_buffer()),
-        saved_typed_data_(reader_->typed_data()),
-        saved_offset_(reader_->offset()) {}
-
-  ~AlternativeReadingScope() {
+  ~AlternativeReadingScopeWithNewData() {
     reader_->set_raw_buffer(saved_raw_buffer_);
     reader_->set_typed_data(saved_typed_data_);
     reader_->set_size(saved_size_);
@@ -452,7 +459,7 @@
   const ExternalTypedData* saved_typed_data_;
   intptr_t saved_offset_;
 
-  DISALLOW_COPY_AND_ASSIGN(AlternativeReadingScope);
+  DISALLOW_COPY_AND_ASSIGN(AlternativeReadingScopeWithNewData);
 };
 
 // A helper class that resets the readers min and max positions both upon
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index b591aef..e0631b8 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -1815,7 +1815,7 @@
         }
         const intptr_t offset_in_constant_table = helper_.ReadUInt();
 
-        AlternativeReadingScope scope(
+        AlternativeReadingScopeWithNewData scope(
             &helper_.reader_,
             &ExternalTypedData::Handle(Z,
                                        kernel_program_info_.constants_table()),
diff --git a/runtime/vm/lockers.cc b/runtime/vm/lockers.cc
index 79f6f25..ca5c671 100644
--- a/runtime/vm/lockers.cc
+++ b/runtime/vm/lockers.cc
@@ -101,4 +101,22 @@
   }
 }
 
+ReadRwLocker::ReadRwLocker(ThreadState* thread_state, RwLock* rw_lock)
+    : StackResource(thread_state), rw_lock_(rw_lock) {
+  rw_lock_->EnterRead();
+}
+
+ReadRwLocker::~ReadRwLocker() {
+  rw_lock_->LeaveRead();
+}
+
+WriteRwLocker::WriteRwLocker(ThreadState* thread_state, RwLock* rw_lock)
+    : StackResource(thread_state), rw_lock_(rw_lock) {
+  rw_lock_->EnterWrite();
+}
+
+WriteRwLocker::~WriteRwLocker() {
+  rw_lock_->LeaveWrite();
+}
+
 }  // namespace dart
diff --git a/runtime/vm/lockers.h b/runtime/vm/lockers.h
index de62b6c..3e81788 100644
--- a/runtime/vm/lockers.h
+++ b/runtime/vm/lockers.h
@@ -252,6 +252,91 @@
   DISALLOW_COPY_AND_ASSIGN(SafepointMonitorLocker);
 };
 
+class RwLock {
+ public:
+  RwLock() {}
+  ~RwLock() {}
+
+ private:
+  friend class ReadRwLocker;
+  friend class WriteRwLocker;
+
+  void EnterRead() {
+    MonitorLocker ml(&monitor_);
+    while (state_ == -1) {
+      ml.Wait();
+    }
+    ++state_;
+  }
+  void LeaveRead() {
+    MonitorLocker ml(&monitor_);
+    ASSERT(state_ > 0);
+    if (--state_ == 0) {
+      ml.NotifyAll();
+    }
+  }
+
+  void EnterWrite() {
+    MonitorLocker ml(&monitor_);
+    while (state_ != 0) {
+      ml.Wait();
+    }
+    state_ = -1;
+  }
+  void LeaveWrite() {
+    MonitorLocker ml(&monitor_);
+    ASSERT(state_ == -1);
+    state_ = 0;
+    ml.NotifyAll();
+  }
+
+  Monitor monitor_;
+  // [state_] > 0  : The lock is held by multiple readers.
+  // [state_] == 0 : The lock is free (no readers/writers).
+  // [state_] == -1: The lock is held by a single writer.
+  intptr_t state_ = 0;
+};
+
+/*
+ * Locks a given [RwLock] for reading purposes.
+ *
+ * It will block while the lock is held by a writer.
+ *
+ * If this locker is long'jmped over (e.g. on a background compiler thread) the
+ * lock will be freed.
+ *
+ * NOTE: If the locking operation blocks (due to a writer) it will not check
+ * for a pending safepoint operation.
+ */
+class ReadRwLocker : public StackResource {
+ public:
+  ReadRwLocker(ThreadState* thread_state, RwLock* rw_lock);
+  ~ReadRwLocker();
+
+ private:
+  RwLock* rw_lock_;
+};
+
+/*
+ * Locks a given [RwLock] for writing purposes.
+ *
+ * It will block while the lock is held by one or more readers.
+ *
+ * If this locker is long'jmped over (e.g. on a background compiler thread) the
+ * lock will be freed.
+ *
+ * NOTE: If the locking operation blocks (due to a writer) it will not check
+ * for a pending safepoint operation.
+ */
+class WriteRwLocker : public StackResource {
+ public:
+  WriteRwLocker(ThreadState* thread_state, RwLock* rw_lock);
+  ~WriteRwLocker();
+
+ private:
+  RwLock* rw_lock_;
+};
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_LOCKERS_H_
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index c541cd2..007878e 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1931,6 +1931,15 @@
     }
     object_store->set_bootstrap_library(ObjectStore::kWasm, lib);
 
+#define REGISTER_WASM_TYPE(clazz)                                              \
+  cls = Class::New<Instance>(k##clazz##Cid, isolate);                          \
+  cls.set_num_type_arguments(0);                                               \
+  cls.set_is_prefinalized();                                                   \
+  pending_classes.Add(cls);                                                    \
+  RegisterClass(cls, Symbols::clazz(), lib);
+    CLASS_LIST_WASM(REGISTER_WASM_TYPE);
+#undef REGISTER_WASM_TYPE
+
     // Finish the initialization by compiling the bootstrap scripts containing
     // the base interfaces and the implementation of the internal classes.
     const Error& error = Error::Handle(
@@ -2025,6 +2034,11 @@
     CLASS_LIST_FFI_TYPE_MARKER(REGISTER_FFI_CLASS);
 #undef REGISTER_FFI_CLASS
 
+#define REGISTER_WASM_CLASS(clazz)                                             \
+  cls = Class::New<Instance>(k##clazz##Cid, isolate);
+    CLASS_LIST_WASM(REGISTER_WASM_CLASS);
+#undef REGISTER_WASM_CLASS
+
     cls = Class::New<Instance>(kFfiNativeFunctionCid, isolate);
 
     cls = Class::NewPointerClass(kFfiPointerCid, isolate);
@@ -3173,16 +3187,6 @@
   return result.raw();
 }
 
-RawFunction* Function::GetTargetOfDynamicInvocationForwarder() const {
-  ASSERT(IsDynamicInvocationForwarder());
-  auto& func_name = String::Handle(name());
-  func_name = DemangleDynamicInvocationForwarderName(func_name);
-  const auto& owner = Class::Handle(Owner());
-  RawFunction* target = owner.LookupDynamicFunction(func_name);
-  ASSERT(target != Function::null());
-  return target;
-}
-
 #endif
 
 bool AbstractType::InstantiateAndTestSubtype(
@@ -9372,13 +9376,12 @@
 
 void Script::LookupSourceAndLineStarts(Zone* zone) const {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  if (Source() == String::null()) {
-    // This is a script without source info.
+  if (!IsLazyLookupSourceAndLineStarts()) {
     return;
   }
   const String& uri = String::Handle(zone, resolved_url());
   ASSERT(uri.IsSymbol());
-  if (uri.Length() > 0 && Source() == Symbols::Empty().raw()) {
+  if (uri.Length() > 0) {
     // Entry included only to provide URI - actual source should already exist
     // in the VM, so try to find it.
     Library& lib = Library::Handle(zone);
@@ -9388,18 +9391,18 @@
     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 &&
-          script.Source() != Symbols::Empty().raw()) {
-        set_source(String::Handle(zone, script.Source()));
-        set_line_starts(TypedData::Handle(zone, script.line_starts()));
-        // Note that we may find a script without source info (null source).
-        // We will not repeat the lookup in this case.
-        return;
+      if (!script.IsNull() && script.kind() == RawScript::kKernelTag) {
+        const auto& source = String::Handle(zone, script.Source());
+        const auto& line_starts = TypedData::Handle(zone, script.line_starts());
+        if (!source.IsNull() || !line_starts.IsNull()) {
+          set_source(source);
+          set_line_starts(line_starts);
+          break;
+        }
       }
     }
-    set_source(Object::null_string());
-    // No script found. Set source to null to prevent further lookup.
   }
+  SetLazyLookupSourceAndLineStarts(false);
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 }
 
@@ -9503,16 +9506,28 @@
 }
 
 RawArray* Script::yield_positions() const {
-#if !defined(DART_PRECOMPILED_RUNTIME)
-  Array& yields = Array::Handle(raw_ptr()->yield_positions_);
-  if (yields.IsNull() && kind() == RawScript::kKernelTag) {
-    // This is created lazily. Now we need it.
-    kernel::CollectTokenPositionsFor(*this);
-  }
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
   return raw_ptr()->yield_positions_;
 }
 
+RawGrowableObjectArray* Script::GetYieldPositions(
+    const Function& function) const {
+  if (!function.IsAsyncClosure() && !function.IsAsyncGenClosure())
+    return GrowableObjectArray::null();
+  ASSERT(!function.is_declared_in_bytecode());
+  Compiler::ComputeYieldPositions(function);
+  UnorderedHashMap<SmiTraits> function_map(raw_ptr()->yield_positions_);
+  const auto& key = Smi::Handle(Smi::New(function.token_pos().value()));
+  intptr_t entry = function_map.FindKey(key);
+  GrowableObjectArray& array = GrowableObjectArray::Handle();
+  if (entry < 0) {
+    array ^= GrowableObjectArray::null();
+  } else {
+    array ^= function_map.GetPayload(entry, 0);
+  }
+  function_map.Release();
+  return array.raw();
+}
+
 RawTypedData* Script::line_starts() const {
   return raw_ptr()->line_starts_;
 }
@@ -9529,7 +9544,22 @@
 }
 
 void Script::set_kind(RawScript::Kind value) const {
-  StoreNonPointer(&raw_ptr()->kind_, value);
+  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::SetLazyLookupSourceAndLineStarts(bool value) const {
+  set_kind_and_tags(RawScript::LazyLookupSourceAndLineStartsBit::update(
+      value, raw_ptr()->kind_and_tags_));
+}
+
+bool Script::IsLazyLookupSourceAndLineStarts() const {
+  return RawScript::LazyLookupSourceAndLineStartsBit::decode(
+      raw_ptr()->kind_and_tags_);
 }
 
 void Script::set_load_timestamp(int64_t value) const {
@@ -9805,6 +9835,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_kernel_script_index(0);
   result.set_load_timestamp(
@@ -11399,8 +11430,10 @@
     const String& klass,
     const Array& arguments,
     const TypeArguments& type_arguments) {
+  Zone* zone = Thread::Current()->zone();
 #if defined(DART_PRECOMPILED_RUNTIME)
   const String& error_str = String::Handle(
+      zone,
       String::New("Expression evaluation not available in precompiled mode."));
   return ApiError::New(error_str);
 #else
@@ -11409,36 +11442,51 @@
 
   if (kernel_pgm == NULL) {
     return ApiError::New(String::Handle(
-        String::New("Kernel isolate returned ill-formed kernel.")));
+        zone, String::New("Kernel isolate returned ill-formed kernel.")));
   }
 
   kernel::KernelLoader loader(kernel_pgm.get(),
                               /*uri_to_source_table=*/nullptr);
-  const Object& result = Object::Handle(
-      loader.LoadExpressionEvaluationFunction(library_url, klass));
+  auto& result = Object::Handle(
+      zone, loader.LoadExpressionEvaluationFunction(library_url, klass));
   kernel_pgm.reset();
 
   if (result.IsError()) return result.raw();
 
-  const Function& callee = Function::Cast(result);
+  const auto& callee = Function::CheckedHandle(zone, result.raw());
 
   // type_arguments is null if all type arguments are dynamic.
   if (type_definitions.Length() == 0 || type_arguments.IsNull()) {
-    return DartEntry::InvokeFunction(callee, arguments);
+    result = DartEntry::InvokeFunction(callee, arguments);
+  } else {
+    intptr_t num_type_args = type_arguments.Length();
+    Array& real_arguments =
+        Array::Handle(zone, Array::New(arguments.Length() + 1));
+    real_arguments.SetAt(0, type_arguments);
+    Object& arg = Object::Handle(zone);
+    for (intptr_t i = 0; i < arguments.Length(); ++i) {
+      arg = arguments.At(i);
+      real_arguments.SetAt(i + 1, arg);
+    }
+
+    const Array& args_desc = Array::Handle(
+        zone, ArgumentsDescriptor::New(num_type_args, arguments.Length()));
+    result = DartEntry::InvokeFunction(callee, real_arguments, args_desc);
   }
 
-  intptr_t num_type_args = type_arguments.Length();
-  Array& real_arguments = Array::Handle(Array::New(arguments.Length() + 1));
-  real_arguments.SetAt(0, type_arguments);
-  Object& arg = Object::Handle();
-  for (intptr_t i = 0; i < arguments.Length(); ++i) {
-    arg = arguments.At(i);
-    real_arguments.SetAt(i + 1, arg);
+  if (callee.is_declared_in_bytecode()) {
+    // Expression evaluation binary expires immediately after evaluation is
+    // finished. However, hot reload may still find corresponding
+    // KernelProgramInfo object in the heap and it would try to patch it.
+    // To prevent accessing stale kernel binary in ResetObjectTable, bytecode
+    // component of the callee's KernelProgramInfo is reset here.
+    const auto& script = Script::Handle(zone, callee.script());
+    const auto& info =
+        KernelProgramInfo::Handle(zone, script.kernel_program_info());
+    info.set_bytecode_component(Object::null_array());
   }
 
-  const Array& args_desc = Array::Handle(
-      ArgumentsDescriptor::New(num_type_args, arguments.Length()));
-  return DartEntry::InvokeFunction(callee, real_arguments, args_desc);
+  return result.raw();
 #endif
 }
 
@@ -12447,6 +12495,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;
@@ -13019,7 +13082,6 @@
                                        uword handler_pc_offset,
                                        bool needs_stacktrace,
                                        bool has_catch_all,
-                                       TokenPosition token_pos,
                                        bool is_generated) const {
   ASSERT((try_index >= 0) && (try_index < num_entries()));
   NoSafepointScope no_safepoint;
@@ -13408,7 +13470,7 @@
   }
 }
 
-bool ICData::RebindRuleFromCString(const char* str, RebindRule* out) {
+bool ICData::ParseRebindRule(const char* str, RebindRule* out) {
 #define RULE_CASE(Name)                                                        \
   if (strcmp(str, #Name) == 0) {                                               \
     *out = RebindRule::k##Name;                                                \
@@ -14388,6 +14450,39 @@
 
 Code::Comments::Comments(const Array& comments) : comments_(comments) {}
 
+const char* Code::EntryKindToCString(EntryKind kind) {
+  switch (kind) {
+    case EntryKind::kNormal:
+      return "Normal";
+    case EntryKind::kUnchecked:
+      return "Unchecked";
+    case EntryKind::kMonomorphic:
+      return "Monomorphic";
+    case EntryKind::kMonomorphicUnchecked:
+      return "MonomorphicUnchecked";
+    default:
+      UNREACHABLE();
+      return nullptr;
+  }
+}
+
+bool Code::ParseEntryKind(const char* str, EntryKind* out) {
+  if (strcmp(str, "Normal") == 0) {
+    *out = EntryKind::kNormal;
+    return true;
+  } else if (strcmp(str, "Unchecked") == 0) {
+    *out = EntryKind::kUnchecked;
+    return true;
+  } else if (strcmp(str, "Monomorphic") == 0) {
+    *out = EntryKind::kMonomorphic;
+    return true;
+  } else if (strcmp(str, "MonomorphicUnchecked") == 0) {
+    *out = EntryKind::kMonomorphicUnchecked;
+    return true;
+  }
+  return false;
+}
+
 RawLocalVarDescriptors* Code::GetLocalVarDescriptors() const {
   const LocalVarDescriptors& v = LocalVarDescriptors::Handle(var_descriptors());
   if (v.IsNull()) {
@@ -18595,6 +18690,10 @@
     // Out of range.
     return Integer::null();
   }
+  return NewCanonical(value);
+}
+
+RawInteger* Integer::NewCanonical(int64_t value) {
   if (Smi::IsValid(value)) {
     return Smi::New(static_cast<intptr_t>(value));
   }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 37aba42..33a9dad 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1810,7 +1810,7 @@
         kNumRebindRules,
   };
   static const char* RebindRuleToCString(RebindRule r);
-  static bool RebindRuleFromCString(const char* str, RebindRule* out);
+  static bool ParseRebindRule(const char* str, RebindRule* out);
   RebindRule rebind_rule() const;
   void set_rebind_rule(uint32_t rebind_rule) const;
 
@@ -2017,6 +2017,8 @@
   }
 
  private:
+  friend class FlowGraphSerializer;  // For is_megamorphic()
+
   static RawICData* New();
 
   // Grows the array and also sets the argument to the index that should be used
@@ -2990,8 +2992,6 @@
 
   RawFunction* GetDynamicInvocationForwarder(const String& mangled_name,
                                              bool allow_add = true) const;
-
-  RawFunction* GetTargetOfDynamicInvocationForwarder() const;
 #endif
 
   // Slow function, use in asserts to track changes in important library
@@ -3840,9 +3840,11 @@
 
   void LookupSourceAndLineStarts(Zone* zone) const;
   RawGrowableObjectArray* GenerateLineNumberArray() const;
+
   RawScript::Kind kind() const {
-    return static_cast<RawScript::Kind>(raw_ptr()->kind_);
+    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_; }
@@ -3877,6 +3879,8 @@
 
   RawArray* yield_positions() const;
 
+  RawGrowableObjectArray* GetYieldPositions(const Function& function) const;
+
   RawLibrary* FindLibrary() const;
   RawString* GetLine(intptr_t line_number,
                      Heap::Space space = Heap::kNew) const;
@@ -3920,10 +3924,14 @@
                             intptr_t kernel_buffer_len) const;
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
+  void SetLazyLookupSourceAndLineStarts(bool value) const;
+  bool IsLazyLookupSourceAndLineStarts() const;
+
  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_load_timestamp(int64_t value) const;
   RawArray* debug_positions() const;
 
@@ -4783,19 +4791,16 @@
   }
 
   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;
+    // OS::PreferredCodeAlignment() is smaller than kObjectAlignment for
+    // simarm_x64.
+    const intptr_t alignment =
+        Utils::Maximum(OS::PreferredCodeAlignment(), kObjectAlignment);
+    return Utils::RoundUp(HeaderSize() + size, alignment);
   }
 
   static intptr_t HeaderSize() {
     intptr_t alignment = OS::PreferredCodeAlignment();
     intptr_t aligned_size = Utils::RoundUp(sizeof(RawInstructions), alignment);
-#if !defined(IS_SIMARM_X64)
-    ASSERT(aligned_size == alignment);
-#endif  // !defined(IS_SIMARM_X64)
     return aligned_size;
   }
 
@@ -4814,19 +4819,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_;
@@ -5168,7 +5162,6 @@
                       uword handler_pc_offset,
                       bool needs_stacktrace,
                       bool has_catch_all,
-                      TokenPosition token_pos,
                       bool is_generated) const;
 
   RawArray* GetHandledTypes(intptr_t try_index) const;
@@ -5232,6 +5225,9 @@
 
   using EntryKind = CodeEntryKind;
 
+  static const char* EntryKindToCString(EntryKind kind);
+  static bool ParseEntryKind(const char* str, EntryKind* out);
+
   static intptr_t entry_point_offset(EntryKind kind = EntryKind::kNormal) {
     switch (kind) {
       case EntryKind::kNormal:
@@ -7292,6 +7288,7 @@
   // Returns a canonical Integer object allocated in the old gen space.
   // Returns null if integer is out of range.
   static RawInteger* NewCanonical(const String& str);
+  static RawInteger* NewCanonical(int64_t value);
 
   static RawInteger* New(int64_t value, Heap::Space space = Heap::kNew);
 
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 8fab9f4..1fe1f7a 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -27,7 +27,6 @@
   M(Isolate, isolate)                                                          \
   M(Math, math)                                                                \
   M(Mirrors, mirrors)                                                          \
-  M(Profiler, profiler)                                                        \
   M(TypedData, typed_data)                                                     \
   M(VMService, _vmservice)                                                     \
   M(Wasm, wasm)
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index ad0e5ae..8592a76 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -2644,14 +2644,10 @@
   exception_handlers ^= ExceptionHandlers::New(kNumEntries);
   const bool kNeedsStackTrace = true;
   const bool kNoStackTrace = false;
-  exception_handlers.SetHandlerInfo(0, -1, 20u, kNeedsStackTrace, false,
-                                    TokenPosition::kNoSource, true);
-  exception_handlers.SetHandlerInfo(1, 0, 30u, kNeedsStackTrace, false,
-                                    TokenPosition::kNoSource, true);
-  exception_handlers.SetHandlerInfo(2, -1, 40u, kNoStackTrace, true,
-                                    TokenPosition::kNoSource, true);
-  exception_handlers.SetHandlerInfo(3, 1, 150u, kNoStackTrace, true,
-                                    TokenPosition::kNoSource, true);
+  exception_handlers.SetHandlerInfo(0, -1, 20u, kNeedsStackTrace, false, true);
+  exception_handlers.SetHandlerInfo(1, 0, 30u, kNeedsStackTrace, false, true);
+  exception_handlers.SetHandlerInfo(2, -1, 40u, kNoStackTrace, true, true);
+  exception_handlers.SetHandlerInfo(3, 1, 150u, kNoStackTrace, true, true);
 
   extern void GenerateIncrement(compiler::Assembler * assembler);
   compiler::ObjectPoolBuilder object_pool_builder;
diff --git a/runtime/vm/os.h b/runtime/vm/os.h
index af98eb1..f36bf2e 100644
--- a/runtime/vm/os.h
+++ b/runtime/vm/os.h
@@ -69,7 +69,7 @@
 
   // This constant is guaranteed to be greater or equal to the
   // preferred code alignment on all platforms.
-  static const int kMaxPreferredCodeAlignment = 32;
+  static const int kMaxPreferredCodeAlignment = 16;
 
   // Returns the preferred code alignment or zero if
   // the platform doesn't care. Guaranteed to be a power of two.
diff --git a/runtime/vm/os_android.cc b/runtime/vm/os_android.cc
index 38168ad..9c105a9 100644
--- a/runtime/vm/os_android.cc
+++ b/runtime/vm/os_android.cc
@@ -204,9 +204,9 @@
 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;
+#elif defined(TARGET_ARCH_ARM)
+  const int kMinimumAlignment = 8;
 #else
 #error Unsupported architecture.
 #endif
diff --git a/runtime/vm/os_fuchsia.cc b/runtime/vm/os_fuchsia.cc
index 4eaae29..56dc743 100644
--- a/runtime/vm/os_fuchsia.cc
+++ b/runtime/vm/os_fuchsia.cc
@@ -153,9 +153,9 @@
 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;
+#elif defined(TARGET_ARCH_ARM)
+  const int kMinimumAlignment = 8;
 #else
 #error Unsupported architecture.
 #endif
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index 9baba7e..65541b0 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -516,9 +516,9 @@
 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;
+#elif defined(TARGET_ARCH_ARM)
+  const int kMinimumAlignment = 8;
 #else
 #error Unsupported architecture.
 #endif
diff --git a/runtime/vm/os_macos.cc b/runtime/vm/os_macos.cc
index 4788b6c..5518b4a 100644
--- a/runtime/vm/os_macos.cc
+++ b/runtime/vm/os_macos.cc
@@ -154,9 +154,9 @@
 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;
+#elif defined(TARGET_ARCH_ARM)
+  const int kMinimumAlignment = 8;
 #else
 #error Unsupported architecture.
 #endif
diff --git a/runtime/vm/os_win.cc b/runtime/vm/os_win.cc
index c0f8e39..fa7a880 100644
--- a/runtime/vm/os_win.cc
+++ b/runtime/vm/os_win.cc
@@ -191,12 +191,12 @@
 }
 
 intptr_t OS::PreferredCodeAlignment() {
-  ASSERT(32 <= OS::kMaxPreferredCodeAlignment);
+  ASSERT(16 <= 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;
+#elif defined(TARGET_ARCH_ARM)
+  return 8;
 #else
 #error Unsupported architecture.
 #endif
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index fee9e8e..a8f25d3 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -57,6 +57,15 @@
             false,
             "Collect native stack traces when tracing Dart allocations.");
 
+DEFINE_FLAG(
+    int,
+    sample_buffer_duration,
+    0,
+    "Defines the size of the profiler sample buffer to contain at least "
+    "N seconds of samples at a given sample rate. If not provided, the "
+    "default is ~4 seconds. Large values will greatly increase memory "
+    "consumption.");
+
 #ifndef PRODUCT
 
 bool Profiler::initialized_ = false;
@@ -72,12 +81,13 @@
     return;
   }
   ASSERT(!initialized_);
-  sample_buffer_ = new SampleBuffer();
+  SetSamplePeriod(FLAG_profile_period);
+  intptr_t capacity = CalculateSampleBufferCapacity();
+  sample_buffer_ = new SampleBuffer(capacity);
   Profiler::InitAllocationSampleBuffer();
   // Zero counters.
   memset(&counters_, 0, sizeof(counters_));
   ThreadInterrupter::Init();
-  SetSamplePeriod(FLAG_profile_period);
   ThreadInterrupter::Startup();
   initialized_ = true;
 }
@@ -116,6 +126,25 @@
   }
 }
 
+static intptr_t SamplesPerSecond() {
+  const intptr_t kMicrosPerSec = 1000000;
+  return kMicrosPerSec / FLAG_profile_period;
+}
+
+intptr_t Profiler::CalculateSampleBufferCapacity() {
+  if (FLAG_sample_buffer_duration <= 0) {
+    return SampleBuffer::kDefaultBufferCapacity;
+  }
+  // Deeper stacks require more than a single Sample object to be represented
+  // correctly. These samples are chained, so we need to determine the worst
+  // case sample chain length for a single stack.
+  const intptr_t max_sample_chain_length =
+      FLAG_max_profile_depth / kMaxSamplesPerTick;
+  const intptr_t buffer_size = FLAG_sample_buffer_duration *
+                               SamplesPerSecond() * max_sample_chain_length;
+  return buffer_size;
+}
+
 void Profiler::SetSamplePeriod(intptr_t period) {
   const int kMinimumProfilePeriod = 50;
   if (period < kMinimumProfilePeriod) {
@@ -163,6 +192,18 @@
     OS::PrintErr("Profiler sample is %" Pd " bytes\n", Sample::instance_size());
     OS::PrintErr("Profiler memory usage = %" Pd " bytes\n", size);
   }
+  if (FLAG_sample_buffer_duration != 0) {
+    OS::PrintErr(
+        "** WARNING ** Custom sample buffer size provided via "
+        "--sample-buffer-duration\n");
+    OS::PrintErr(
+        "The sample buffer can hold at least %ds worth of "
+        "samples with stacks depths of up to %d, collected at "
+        "a sample rate of %" Pd "Hz.\n",
+        FLAG_sample_buffer_duration, FLAG_max_profile_depth,
+        SamplesPerSecond());
+    OS::PrintErr("The resulting sample buffer size is %" Pd " bytes.\n", size);
+  }
 }
 
 AllocationSampleBuffer::AllocationSampleBuffer(intptr_t capacity)
diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h
index 9c879ae..c972c40 100644
--- a/runtime/vm/profiler.h
+++ b/runtime/vm/profiler.h
@@ -95,6 +95,13 @@
  private:
   static void DumpStackTrace(uword sp, uword fp, uword pc, bool for_crash);
 
+  // Calculates the sample buffer capacity. Returns
+  // SampleBuffer::kDefaultBufferCapacity if --sample-buffer-duration is not
+  // provided. Otherwise, the capacity is based on the sample rate, maximum
+  // sample stack depth, and the number of seconds of samples the sample buffer
+  // should be able to accomodate.
+  static intptr_t CalculateSampleBufferCapacity();
+
   // Does not walk the thread's stack.
   static void SampleThreadSingleFrame(Thread* thread, uintptr_t pc);
   static bool initialized_;
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index 65e7a5f..e39faf0 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -1413,7 +1413,7 @@
   DisableNativeProfileScope dnps;
   DisableBackgroundCompilationScope dbcs;
   SetFlagScope<int> sfs(&FLAG_optimization_counter_threshold, 30000);
-  SetFlagScope<bool> sfs2(&FLAG_enable_interpreter, false);
+  SetFlagScope<int> sfs2(&FLAG_compilation_counter_threshold, 0);
 
   const char* kScript =
       "class A {\n"
@@ -1532,7 +1532,7 @@
   DisableNativeProfileScope dnps;
   DisableBackgroundCompilationScope dbcs;
   SetFlagScope<int> sfs(&FLAG_optimization_counter_threshold, 30000);
-  SetFlagScope<bool> sfs2(&FLAG_enable_interpreter, false);
+  SetFlagScope<int> sfs2(&FLAG_compilation_counter_threshold, 0);
 
   const char* kScript =
       "class A {\n"
@@ -1850,8 +1850,8 @@
   DisableNativeProfileScope dnps;
   DisableBackgroundCompilationScope dbcs;
   // Optimize quickly.
-  SetFlagScope<int> sfs2(&FLAG_optimization_counter_threshold, 5);
-  SetFlagScope<bool> sfs3(&FLAG_enable_interpreter, false);
+  SetFlagScope<int> sfs(&FLAG_optimization_counter_threshold, 5);
+  SetFlagScope<int> sfs2(&FLAG_compilation_counter_threshold, 0);
   const char* kScript =
       "class A {\n"
       "  var a;\n"
@@ -2020,8 +2020,8 @@
   DisableNativeProfileScope dnps;
   DisableBackgroundCompilationScope dbcs;
   // Optimize quickly.
-  SetFlagScope<int> sfs2(&FLAG_optimization_counter_threshold, 5);
-  SetFlagScope<bool> sfs3(&FLAG_enable_interpreter, false);
+  SetFlagScope<int> sfs(&FLAG_optimization_counter_threshold, 5);
+  SetFlagScope<int> sfs2(&FLAG_compilation_counter_threshold, 0);
 
   const char* kScript =
       "class A {\n"
@@ -2225,8 +2225,8 @@
   DisableNativeProfileScope dnps;
   DisableBackgroundCompilationScope dbcs;
   // Optimize quickly.
-  SetFlagScope<int> sfs2(&FLAG_optimization_counter_threshold, 5);
-  SetFlagScope<bool> sfs3(&FLAG_enable_interpreter, false);
+  SetFlagScope<int> sfs(&FLAG_optimization_counter_threshold, 5);
+  SetFlagScope<int> sfs2(&FLAG_compilation_counter_threshold, 0);
 
   const char* kScript =
       "class A {\n"
@@ -2300,11 +2300,9 @@
     ProfileStackWalker walker(&profile, true);
 
     EXPECT_STREQ("DRT_AllocateObject", walker.VMTagName());
-    if (!FLAG_enable_interpreter) {
-      EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
-      EXPECT_EQ(1, walker.CurrentExclusiveTicks());
-      EXPECT(walker.Down());
-    }
+    EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
+    EXPECT_EQ(1, walker.CurrentExclusiveTicks());
+    EXPECT(walker.Down());
     EXPECT_STREQ("B.boo", walker.CurrentName());
     EXPECT_EQ(1, walker.CurrentInclusiveTicks());
     EXPECT_STREQ("A", walker.CurrentToken());
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 212d274..209363f 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -226,8 +226,8 @@
       ASSERT(use_saved_class_table || class_table->SizeAt(class_id) > 0);
       if (!class_table->IsValidIndex(class_id) ||
           (!class_table->HasValidClassAt(class_id) && !use_saved_class_table)) {
-        FATAL2("Invalid class id: %" Pd " from tags %x\n", class_id,
-               ptr()->tags_);
+        FATAL3("Invalid cid: %" Pd ", obj: %p, tags: %x. Corrupt heap?",
+               class_id, this, ptr()->tags_);
       }
 #endif  // DEBUG
       instance_size = isolate->GetClassSizeForHeapWalkAt(class_id);
@@ -320,6 +320,13 @@
         break;
       }
 #undef RAW_VISITPOINTERS
+#define RAW_VISITPOINTERS(clazz) case k##clazz##Cid:
+      CLASS_LIST_WASM(RAW_VISITPOINTERS) {
+        // These wasm types do not have any fields or type arguments.
+        size = HeapSize();
+        break;
+      }
+#undef RAW_VISITPOINTERS
     case kFreeListElement: {
       uword addr = RawObject::ToAddr(this);
       FreeListElement* element = reinterpret_cast<FreeListElement*>(addr);
@@ -336,8 +343,8 @@
       size = HeapSize();
       break;
     default:
-      OS::PrintErr("Class Id: %" Pd "\n", class_id);
-      UNREACHABLE();
+      FATAL3("Invalid cid: %" Pd ", obj: %p, tags: %x. Corrupt heap?", class_id,
+             this, ptr()->tags_);
       break;
   }
 
@@ -660,7 +667,7 @@
   }
 }
 
-bool RawPcDescriptors::KindFromCString(const char* cstr, Kind* out) {
+bool RawPcDescriptors::ParseKind(const char* cstr, Kind* out) {
   ASSERT(cstr != nullptr && out != nullptr);
 #define ENUM_CASE(name, init)                                                  \
   if (strcmp(#name, cstr) == 0) {                                              \
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 0c88bdc..1820fa8 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -899,7 +899,7 @@
     }
   }
 
-  static bool KindFromCString(const char* str, Kind* out) {
+  static bool ParseKind(const char* str, Kind* out) {
 #define KIND_CASE(Name)                                                        \
   if (strcmp(str, #Name) == 0) {                                               \
     *out = Kind::k##Name;                                                      \
@@ -1162,6 +1162,12 @@
     kEvaluateTag,
     kKernelTag,
   };
+  enum {
+    kKindPos = 0,
+    kKindSize = 3,
+    kLazyLookupSourceAndLineStartsPos = kKindPos + kKindSize,
+    kLazyLookupSourceAndLineStartsSize = 1,
+  };
 
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(Script);
@@ -1194,7 +1200,15 @@
 
   int32_t line_offset_;
   int32_t col_offset_;
-  int8_t kind_;  // Of type Kind.
+
+  using KindBits = BitField<uint8_t, Kind, kKindPos, kKindSize>;
+  using LazyLookupSourceAndLineStartsBit =
+      BitField<uint8_t,
+               bool,
+               kLazyLookupSourceAndLineStartsPos,
+               kLazyLookupSourceAndLineStartsSize>;
+  uint8_t kind_and_tags_;
+
   intptr_t kernel_script_index_;
   int64_t load_timestamp_;
 };
@@ -1464,15 +1478,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); }
 
@@ -1527,7 +1532,7 @@
   };
 
   static const char* KindToCString(Kind k);
-  static bool KindFromCString(const char* cstr, Kind* out);
+  static bool ParseKind(const char* cstr, Kind* out);
 
   class MergedKindTry {
    public:
diff --git a/runtime/vm/regexp_assembler_ir.cc b/runtime/vm/regexp_assembler_ir.cc
index f7f18ac..65d81e2 100644
--- a/runtime/vm/regexp_assembler_ir.cc
+++ b/runtime/vm/regexp_assembler_ir.cc
@@ -363,7 +363,7 @@
 
 ConstantInstr* IRRegExpMacroAssembler::Int64Constant(int64_t value) const {
   return new (Z)
-      ConstantInstr(Integer::ZoneHandle(Z, Integer::New(value, Heap::kOld)));
+      ConstantInstr(Integer::ZoneHandle(Z, Integer::NewCanonical(value)));
 }
 
 ConstantInstr* IRRegExpMacroAssembler::Uint64Constant(uint64_t value) const {
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 98539e3..68cc4a7 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -3902,6 +3902,18 @@
   return GetAllocationProfileImpl(thread, js, true);
 }
 
+static const MethodParameter* collect_all_garbage_params[] = {
+    RUNNABLE_ISOLATE_PARAMETER,
+    NULL,
+};
+
+static bool CollectAllGarbage(Thread* thread, JSONStream* js) {
+  Isolate* isolate = thread->isolate();
+  isolate->heap()->CollectAllGarbage(Heap::kDebugging);
+  PrintSuccess(js);
+  return true;
+}
+
 static const MethodParameter* get_heap_map_params[] = {
     RUNNABLE_ISOLATE_PARAMETER, NULL,
 };
@@ -4154,6 +4166,7 @@
     // load the source before sending the response.
     if (obj.IsScript()) {
       const Script& script = Script::Cast(obj);
+      script.LookupSourceAndLineStarts(thread->zone());
       if (!script.HasSource() && script.IsPartOfDartColonLibrary() &&
           Service::HasDartLibraryKernelForSources()) {
         const uint8_t* kernel_buffer = Service::dart_library_kernel();
@@ -4747,6 +4760,8 @@
     set_vm_name_params },
   { "setVMTimelineFlags", SetVMTimelineFlags,
     set_vm_timeline_flags_params },
+  { "_collectAllGarbage", CollectAllGarbage,
+    collect_all_garbage_params },
   { "_getDefaultClassesAliases", GetDefaultClassesAliases,
     get_default_classes_aliases_params },
 };
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index 619c72e..a0993b7 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -927,9 +927,10 @@
   argdesc_ = args_desc;
 }
 
-// Note: functions below are marked DART_NOINLINE to recover performance on
-// ARM where inlining these functions into the interpreter loop seemed to cause
-// some code quality issues.
+// 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,
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 59bc7a3..5e161d9 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -585,6 +585,13 @@
     functions = cls.functions();
     for (int i = 0; i < functions.Length(); i++) {
       func ^= functions.At(i);
+      // Skip getter functions of static const field.
+      if (func.kind() == RawFunction::kImplicitStaticGetter) {
+        field ^= func.accessor_field();
+        if (field.is_const() && field.is_static()) {
+          continue;
+        }
+      }
       VisitFunction(jsarr, func);
     }
 
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index d22df2b..097510e 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -178,40 +178,43 @@
     const char* name = cls.ToCString();
     compiler::StubCodeCompiler::GenerateAllocationStubForClass(&assembler, cls);
 
-    if (thread->IsMutatorThread()) {
-      stub = Code::FinalizeCodeAndNotify(name, nullptr, &assembler,
-                                         pool_attachment,
-                                         /*optimized1*/ false);
+    auto mutator_fun = [&]() {
+      stub = Code::FinalizeCode(nullptr, &assembler, pool_attachment,
+                                /*optimized=*/false,
+                                /*stats=*/nullptr);
       // Check if background compilation thread has not already added the stub.
       if (cls.allocation_stub() == Code::null()) {
         stub.set_owner(cls);
         cls.set_allocation_stub(stub);
       }
-    } else {
-      // This part of stub code generation must be at a safepoint.
-      // Stop mutator thread before creating the instruction object and
-      // installing code.
-      // Mutator thread may not run code while we are creating the
-      // instruction object, since the creation of instruction object
-      // changes code page access permissions (makes them temporary not
-      // executable).
-      {
-        ForceGrowthSafepointOperationScope safepoint_scope(thread);
-        stub = cls.allocation_stub();
-        // Check if stub was already generated.
-        if (!stub.IsNull()) {
-          return stub.raw();
-        }
-        stub = Code::FinalizeCode(nullptr, &assembler, pool_attachment,
-                                  /*optimized=*/false, /*stats=*/nullptr);
-        stub.set_owner(cls);
-        cls.set_allocation_stub(stub);
+    };
+    auto bg_compiler_fun = [&]() {
+      ForceGrowthSafepointOperationScope safepoint_scope(thread);
+      stub = cls.allocation_stub();
+      // Check if stub was already generated.
+      if (!stub.IsNull()) {
+        return;
       }
+      stub = Code::FinalizeCode(nullptr, &assembler, pool_attachment,
+                                /*optimized=*/false, /*stats=*/nullptr);
+      stub.set_owner(cls);
+      cls.set_allocation_stub(stub);
+    };
 
-      // We notify code observers after finalizing the code in order to be
-      // outside a [SafepointOperationScope].
-      Code::NotifyCodeObservers(name, stub, /*optimized=*/false);
-    }
+    // We have to ensure no mutators are running, because:
+    //
+    //   a) We allocate an instructions object, which might cause us to
+    //      temporarily flip page protections from (RX -> RW -> RX).
+    //
+    //   b) To ensure only one thread succeeds installing an allocation for the
+    //      given class.
+    //
+    thread->isolate_group()->RunWithStoppedMutators(
+        mutator_fun, bg_compiler_fun, /*use_force_growth=*/true);
+
+    // We notify code observers after finalizing the code in order to be
+    // outside a [SafepointOperationScope].
+    Code::NotifyCodeObservers(name, stub, /*optimized=*/false);
 #ifndef PRODUCT
     if (FLAG_support_disassembler && FLAG_disassemble_stubs) {
       LogBlock lb;
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 31bb9e7..c0f5f16 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -89,8 +89,8 @@
   V(DartSchemePrivate, "dart:_")                                               \
   V(DartTypedData, "dart:typed_data")                                          \
   V(DartVMProduct, "dart.vm.product")                                          \
-  V(DartVMServiceIO, "dart:vmservice_io")                                      \
   V(DartVMService, "dart:_vmservice")                                          \
+  V(DartVMServiceIO, "dart:vmservice_io")                                      \
   V(DebugClassName, "#DebugClass")                                             \
   V(DebugProcedureName, ":Eval")                                               \
   V(Default, "Default")                                                        \
@@ -158,6 +158,7 @@
   V(FutureValue, "Future.value")                                               \
   V(Get, "get")                                                                \
   V(GetCall, "get:call")                                                       \
+  V(GetLength, "get:length")                                                   \
   V(GetRuntimeType, "get:runtimeType")                                         \
   V(GetterPrefix, "get:")                                                      \
   V(GreaterEqualOperator, ">=")                                                \
@@ -191,7 +192,6 @@
   V(LanguageError, "LanguageError")                                            \
   V(LeftShiftOperator, "<<")                                                   \
   V(Length, "length")                                                          \
-  V(GetLength, "get:length")                                                   \
   V(LessEqualOperator, "<=")                                                   \
   V(LibraryClass, "Library")                                                   \
   V(LibraryPrefix, "LibraryPrefix")                                            \
@@ -262,8 +262,8 @@
   V(ThrowNew, "_throwNew")                                                     \
   V(ThrowNewInvocation, "_throwNewInvocation")                                 \
   V(TopLevel, "::")                                                            \
-  V(TruncDivOperator, "~/")                                                    \
   V(TransferableTypedData, "TransferableTypedData")                            \
+  V(TruncDivOperator, "~/")                                                    \
   V(TryFinallyReturnValue, ":try_finally_return_value")                        \
   V(TwoByteString, "_TwoByteString")                                           \
   V(TwoSpaces, "  ")                                                           \
@@ -285,6 +285,11 @@
   V(UnwindError, "UnwindError")                                                \
   V(Value, "value")                                                            \
   V(Values, "values")                                                          \
+  V(WasmInt32, "Int32")                                                        \
+  V(WasmInt64, "Int64")                                                        \
+  V(WasmFloat, "Float")                                                        \
+  V(WasmDouble, "Double")                                                      \
+  V(WasmVoid, "Void")                                                          \
   V(YieldKw, "yield")                                                          \
   V(_AsyncAwaitCompleter, "_AsyncAwaitCompleter")                              \
   V(_AsyncAwaitCompleterConstructor, "_AsyncAwaitCompleter.")                  \
@@ -298,8 +303,10 @@
   V(_ByteBufferDot_New, "_ByteBuffer._New")                                    \
   V(_ByteDataView, "_ByteDataView")                                            \
   V(_CapabilityImpl, "_CapabilityImpl")                                        \
+  V(_ClassMirror, "_ClassMirror")                                              \
   V(_Closure, "_Closure")                                                      \
   V(_ClosureCall, "_Closure.call")                                             \
+  V(_CombinatorMirror, "_CombinatorMirror")                                    \
   V(_CompileTimeError, "_CompileTimeError")                                    \
   V(_CompleteOnAsyncReturn, "_completeOnAsyncReturn")                          \
   V(_DeletedEnumPrefix, "Deleted enum value from ")                            \
@@ -333,6 +340,7 @@
   V(_Float64x2ArrayFactory, "Float64x2List.")                                  \
   V(_Float64x2ArrayView, "_Float64x2ArrayView")                                \
   V(_Float64x2List, "_Float64x2List")                                          \
+  V(_FunctionTypeMirror, "_FunctionTypeMirror")                                \
   V(_GrowableList, "_GrowableList")                                            \
   V(_GrowableListFactory, "_GrowableList.")                                    \
   V(_GrowableListWithData, "_GrowableList._withData")                          \
@@ -354,30 +362,23 @@
   V(_Int8ArrayView, "_Int8ArrayView")                                          \
   V(_Int8List, "_Int8List")                                                    \
   V(_IntegerImplementation, "_IntegerImplementation")                          \
+  V(_IsolateMirror, "_IsolateMirror")                                          \
+  V(_LibraryDependencyMirror, "_LibraryDependencyMirror")                      \
+  V(_LibraryMirror, "_LibraryMirror")                                          \
   V(_LibraryPrefix, "_LibraryPrefix")                                          \
   V(_LinkedHashMap, "_InternalLinkedHashMap")                                  \
   V(_LinkedHashSet, "_CompactLinkedHashSet")                                   \
   V(_List, "_List")                                                            \
   V(_ListFactory, "_List.")                                                    \
-  V(_LocalClassMirror, "_LocalClassMirror")                                    \
-  V(_LocalCombinatorMirror, "_LocalCombinatorMirror")                          \
-  V(_LocalFunctionTypeMirror, "_LocalFunctionTypeMirror")                      \
-  V(_LocalIsolateMirror, "_LocalIsolateMirror")                                \
-  V(_LocalLibraryDependencyMirror, "_LocalLibraryDependencyMirror")            \
-  V(_LocalLibraryMirror, "_LocalLibraryMirror")                                \
-  V(_LocalMethodMirror, "_LocalMethodMirror")                                  \
-  V(_LocalMirrorSystem, "_LocalMirrorSystem")                                  \
-  V(_LocalParameterMirror, "_LocalParameterMirror")                            \
-  V(_LocalTypeVariableMirror, "_LocalTypeVariableMirror")                      \
-  V(_LocalTypedefMirror, "_LocalTypedefMirror")                                \
-  V(_LocalVariableMirror, "_LocalVariableMirror")                              \
+  V(_MethodMirror, "_MethodMirror")                                            \
   V(_Mint, "_Mint")                                                            \
   V(_MirrorReference, "_MirrorReference")                                      \
+  V(_MirrorSystem, "_MirrorSystem")                                            \
+  V(_ParameterMirror, "_ParameterMirror")                                      \
   V(_Random, "_Random")                                                        \
   V(_RawReceivePortImpl, "_RawReceivePortImpl")                                \
   V(_RegExp, "_RegExp")                                                        \
   V(_SendPortImpl, "_SendPortImpl")                                            \
-  V(_TransferableTypedDataImpl, "_TransferableTypedDataImpl")                  \
   V(_Smi, "_Smi")                                                              \
   V(_SourceLocation, "_SourceLocation")                                        \
   V(_SpecialTypeMirror, "_SpecialTypeMirror")                                  \
@@ -387,9 +388,12 @@
   V(_SyncIterable, "_SyncIterable")                                            \
   V(_SyncIterableConstructor, "_SyncIterable.")                                \
   V(_SyncIterator, "_SyncIterator")                                            \
+  V(_TransferableTypedDataImpl, "_TransferableTypedDataImpl")                  \
   V(_Type, "_Type")                                                            \
   V(_TypeParameter, "_TypeParameter")                                          \
   V(_TypeRef, "_TypeRef")                                                      \
+  V(_TypeVariableMirror, "_TypeVariableMirror")                                \
+  V(_TypedefMirror, "_TypedefMirror")                                          \
   V(_Uint16ArrayFactory, "Uint16List.")                                        \
   V(_Uint16ArrayView, "_Uint16ArrayView")                                      \
   V(_Uint16List, "_Uint16List")                                                \
@@ -406,6 +410,7 @@
   V(_Uint8ClampedList, "_Uint8ClampedList")                                    \
   V(_Uint8List, "_Uint8List")                                                  \
   V(_UserTag, "_UserTag")                                                      \
+  V(_VariableMirror, "_VariableMirror")                                        \
   V(_WeakProperty, "_WeakProperty")                                            \
   V(_classRangeCheck, "_classRangeCheck")                                      \
   V(_current, "_current")                                                      \
diff --git a/runtime/vm/timeline.h b/runtime/vm/timeline.h
index 6582016..1bce4cc 100644
--- a/runtime/vm/timeline.h
+++ b/runtime/vm/timeline.h
@@ -53,7 +53,7 @@
   V(Embedder, "dart:embedder")                                                 \
   V(GC, "dart:gc")                                                             \
   V(Isolate, "dart:isolate")                                                   \
-  V(Profiler, "dart:profiler")                                                 \
+  V(Developer, "dart:developer")                                               \
   V(VM, "dart:vm")
 
 // A stream of timeline events. A stream has a name and can be enabled or
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index 9d41d66..ac2c84a 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -176,7 +176,8 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
 
 RawCode* TypeTestingStubGenerator::BuildCodeForType(const Type& type) {
-  HierarchyInfo* hi = Thread::Current()->hierarchy_info();
+  auto thread = Thread::Current();
+  HierarchyInfo* hi = thread->hierarchy_info();
   ASSERT(hi != NULL);
 
   if (!hi->CanUseSubtypeRangeCheckFor(type) &&
@@ -195,8 +196,23 @@
   const auto pool_attachment = FLAG_use_bare_instructions
                                    ? Code::PoolAttachment::kNotAttachPool
                                    : Code::PoolAttachment::kAttachPool;
-  const Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
-      name, nullptr, &assembler, pool_attachment, false /* optimized */));
+
+  Code& code = Code::Handle(thread->zone());
+  auto install_code_fun = [&]() {
+    code = Code::FinalizeCode(nullptr, &assembler, pool_attachment,
+                              /*optimized=*/false, /*stats=*/nullptr);
+  };
+
+  // We have to ensure no mutators are running, because:
+  //
+  //   a) We allocate an instructions object, which might cause us to
+  //      temporarily flip page protections from (RX -> RW -> RX).
+  //
+  thread->isolate_group()->RunWithStoppedMutators(
+      install_code_fun, install_code_fun, /*use_force_growth=*/true);
+
+  Code::NotifyCodeObservers(name, code, /*optimized=*/false);
+
   code.set_owner(type);
 #ifndef PRODUCT
   if (FLAG_support_disassembler && FLAG_disassemble_stubs) {
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index 228fc3c..9a4a1c5 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -134,20 +134,16 @@
   ],
 ]
 if (create_kernel_service_snapshot) {
-  _platform_sdk_snapshots += [
-    [
-      "kernel-service",
-      "../utils/kernel-service:kernel-service_snapshot",
-    ],
-  ]
+  _platform_sdk_snapshots += [ [
+        "kernel-service",
+        "../utils/kernel-service:kernel-service_snapshot",
+      ] ]
 }
 if (dart_target_arch != "arm") {
-  _platform_sdk_snapshots += [
-    [
-      "analysis_server",
-      "../utils/analysis_server",
-    ],
-  ]
+  _platform_sdk_snapshots += [ [
+        "analysis_server",
+        "../utils/analysis_server",
+      ] ]
 }
 
 _full_sdk_snapshots = [
@@ -185,20 +181,16 @@
   ],
 ]
 if (create_kernel_service_snapshot) {
-  _full_sdk_snapshots += [
-    [
-      "kernel-service",
-      "../utils/kernel-service:kernel-service_snapshot",
-    ],
-  ]
+  _full_sdk_snapshots += [ [
+        "kernel-service",
+        "../utils/kernel-service:kernel-service_snapshot",
+      ] ]
 }
 if (dart_target_arch != "arm") {
-  _full_sdk_snapshots += [
-    [
-      "analysis_server",
-      "../utils/analysis_server",
-    ],
-  ]
+  _full_sdk_snapshots += [ [
+        "analysis_server",
+        "../utils/analysis_server",
+      ] ]
 }
 
 # Libraries that go under lib/
@@ -222,7 +214,6 @@
   "js_util",
   "math",
   "mirrors",
-  "profiler",
   "svg",
   "typed_data",
   "wasm",
@@ -249,7 +240,6 @@
 #   "isolate",
 #   "math",
 #   "mirrors",
-#   "profiler",
 #   "typed_data",
 # ]
 _platform_sdk_libraries = _full_sdk_libraries
@@ -260,74 +250,82 @@
 
 # This rule copies dartdoc templates to
 # bin/resources/dartdoc/templates
-copy_tree_specs += [ {
-      target = "copy_dartdoc_templates"
-      visibility = [ ":copy_dartdoc_files" ]
-      source = "../third_party/pkg/dartdoc/lib/templates"
-      dest = "$root_out_dir/dart-sdk/bin/resources/dartdoc/templates"
-      ignore_patterns = "{}"
-    } ]
+copy_tree_specs += [
+  {
+    target = "copy_dartdoc_templates"
+    visibility = [ ":copy_dartdoc_files" ]
+    source = "../third_party/pkg/dartdoc/lib/templates"
+    dest = "$root_out_dir/dart-sdk/bin/resources/dartdoc/templates"
+    ignore_patterns = "{}"
+  },
+]
 
 # This rule copies dartdoc resources to
 # bin/resources/dartdoc/resources
-copy_tree_specs += [ {
-      target = "copy_dartdoc_resources"
-      visibility = [ ":copy_dartdoc_files" ]
-      source = "../third_party/pkg/dartdoc/lib/resources"
-      dest = "$root_out_dir/dart-sdk/bin/resources/dartdoc/resources"
-      ignore_patterns = "{}"
-    } ]
+copy_tree_specs += [
+  {
+    target = "copy_dartdoc_resources"
+    visibility = [ ":copy_dartdoc_files" ]
+    source = "../third_party/pkg/dartdoc/lib/resources"
+    dest = "$root_out_dir/dart-sdk/bin/resources/dartdoc/resources"
+    ignore_patterns = "{}"
+  },
+]
 
 # This loop generates rules to copy libraries to lib/
 foreach(library, _full_sdk_libraries) {
-  copy_tree_specs += [ {
-        target = "copy_${library}_library"
-        visibility = [
-          ":copy_platform_sdk_libraries",
-          ":copy_full_sdk_libraries",
-        ]
-        source = "lib/$library"
-        dest = "$root_out_dir/dart-sdk/lib/$library"
-        ignore_patterns = "*.svn,doc,*.py,*.gypi,*.sh,.gitignore"
-      } ]
+  copy_tree_specs += [
+    {
+      target = "copy_${library}_library"
+      visibility = [
+        ":copy_platform_sdk_libraries",
+        ":copy_full_sdk_libraries",
+      ]
+      source = "lib/$library"
+      dest = "$root_out_dir/dart-sdk/lib/$library"
+      ignore_patterns = "*.svn,doc,*.py,*.gypi,*.sh,.gitignore"
+    },
+  ]
 }
 
 if (is_win) {
-  copy_tree_specs += [ {
-        target = "copy_7zip"
-        visibility = [ ":create_common_sdk" ]
-        deps = [
-          ":copy_libraries",
-        ]
-        source = "../third_party/7zip"
-        dest = "$root_out_dir/dart-sdk/lib/_internal/pub/asset/7zip"
-        ignore_patterns = ".svn"
-      } ]
+  copy_tree_specs += [
+    {
+      target = "copy_7zip"
+      visibility = [ ":create_common_sdk" ]
+      deps = [
+        ":copy_libraries",
+      ]
+      source = "../third_party/7zip"
+      dest = "$root_out_dir/dart-sdk/lib/_internal/pub/asset/7zip"
+      ignore_patterns = ".svn"
+    },
+  ]
 }
 
 if (target_cpu == "x64") {
   copy_tree_specs += [
-      {
-        target = "copy_language_model"
-        visibility = [ ":create_common_sdk" ]
-        deps = [
-          ":copy_libraries",
-        ]
-        source = "../pkg/analysis_server/language_model"
-        dest = "$root_out_dir/dart-sdk/model"
-        ignore_patterns = "{}"
-      },
-      {
-        target = "copy_libtensorflowlite_c"
-        visibility = [ ":create_common_sdk" ]
-        deps = [
-          ":copy_libraries",
-        ]
-        source = "../third_party/pkg/tflite_native/lib/src/blobs"
-        dest = "$root_out_dir/dart-sdk/bin/snapshots"
-        ignore_patterns = "{}"
-      }
-   ]
+    {
+      target = "copy_language_model"
+      visibility = [ ":create_common_sdk" ]
+      deps = [
+        ":copy_libraries",
+      ]
+      source = "../pkg/analysis_server/language_model"
+      dest = "$root_out_dir/dart-sdk/model"
+      ignore_patterns = "{}"
+    },
+    {
+      target = "copy_libtensorflowlite_c"
+      visibility = [ ":create_common_sdk" ]
+      deps = [
+        ":copy_libraries",
+      ]
+      source = "../third_party/pkg/tflite_native/lib/src/blobs"
+      dest = "$root_out_dir/dart-sdk/bin/snapshots"
+      ignore_patterns = "{}"
+    },
+  ]
 }
 
 # This generates targets for everything in copy_tree_specs. The targets have the
@@ -399,7 +397,8 @@
   deps = [
     "../runtime/bin:dartaotruntime",
   ]
-  dartaotruntime_out = get_label_info("../runtime/bin:dartaotruntime", "root_out_dir")
+  dartaotruntime_out =
+      get_label_info("../runtime/bin:dartaotruntime", "root_out_dir")
   if (is_win) {
     sources = [
       "$dartaotruntime_out/dartaotruntime.exe",
@@ -421,7 +420,8 @@
   deps = [
     "../runtime/bin:gen_snapshot",
   ]
-  gen_snapshot_out = get_label_info("../runtime/bin:gen_snapshot", "root_out_dir")
+  gen_snapshot_out =
+      get_label_info("../runtime/bin:gen_snapshot", "root_out_dir")
   if (is_win) {
     sources = [
       "$gen_snapshot_out/gen_snapshot.exe",
@@ -663,8 +663,8 @@
   visibility = [ ":copy_dev_compiler_sdk" ]
   deps = [
     ":copy_libraries",
-    "../utils/dartdevc:dartdevc_sdk",
     "../utils/dartdevc:dartdevc_kernel_sdk_outline",
+    "../utils/dartdevc:dartdevc_sdk",
   ]
   gen_dir = get_label_info("../utils/dartdevc:dartdevc_sdk", "target_gen_dir")
   sources = [
@@ -736,8 +736,8 @@
   deps = [
     "../utils/dartdevc:dartdevc_kernel_sdk",
   ]
-  gen_dir = get_label_info("../utils/dartdevc:dartdevc_kernel_sdk",
-                           "target_gen_dir")
+  gen_dir =
+      get_label_info("../utils/dartdevc:dartdevc_kernel_sdk", "target_gen_dir")
   sources = [
     "$gen_dir/kernel/amd/dart_sdk.js",
     "$gen_dir/kernel/amd/dart_sdk.js.map",
@@ -754,8 +754,8 @@
   deps = [
     "../utils/dartdevc:dartdevc_kernel_sdk",
   ]
-  gen_dir = get_label_info("../utils/dartdevc:dartdevc_kernel_sdk",
-                           "target_gen_dir")
+  gen_dir =
+      get_label_info("../utils/dartdevc:dartdevc_kernel_sdk", "target_gen_dir")
   sources = [
     "$gen_dir/kernel/common/dart_sdk.js",
     "$gen_dir/kernel/common/dart_sdk.js.map",
@@ -772,8 +772,8 @@
   deps = [
     "../utils/dartdevc:dartdevc_kernel_sdk",
   ]
-  gen_dir = get_label_info("../utils/dartdevc:dartdevc_kernel_sdk",
-                           "target_gen_dir")
+  gen_dir =
+      get_label_info("../utils/dartdevc:dartdevc_kernel_sdk", "target_gen_dir")
   sources = [
     "$gen_dir/kernel/es6/dart_sdk.js",
     "$gen_dir/kernel/es6/dart_sdk.js.map",
@@ -1006,8 +1006,8 @@
     ":copy_dartdoc_files",
     ":copy_headers",
     ":copy_libraries_dart",
-    ":copy_license",
     ":copy_libraries_specification",
+    ":copy_license",
     ":copy_readme",
     ":copy_vm_dill_files",
     ":write_dartdoc_options",
diff --git a/sdk/lib/_http/websocket_impl.dart b/sdk/lib/_http/websocket_impl.dart
index 8750ccc..ebbce45 100644
--- a/sdk/lib/_http/websocket_impl.dart
+++ b/sdk/lib/_http/websocket_impl.dart
@@ -601,11 +601,11 @@
     data.addAll(const [0x00, 0x00, 0xff, 0xff]);
 
     decoder.process(data, 0, data.length);
-    var result = <int>[];
+    final result = new BytesBuilder();
     List<int> out;
 
     while ((out = decoder.processed()) != null) {
-      result.addAll(out);
+      result.add(out);
     }
 
     if ((serverSide && clientNoContextTakeover) ||
@@ -613,7 +613,7 @@
       decoder = null;
     }
 
-    return new Uint8List.fromList(result);
+    return result.takeBytes();
   }
 
   List<int> processOutgoingMessage(List<int> msg) {
diff --git a/sdk/lib/_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart b/sdk/lib/_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart
index 91d6847..83421ab 100644
--- a/sdk/lib/_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart
+++ b/sdk/lib/_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart
@@ -2,89 +2,88 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/**
- * Support for interoperating with JavaScript.
- *
- * This library provides access to JavaScript objects from Dart, allowing
- * Dart code to get and set properties, and call methods of JavaScript objects
- * and invoke JavaScript functions. The library takes care of converting
- * between Dart and JavaScript objects where possible, or providing proxies if
- * conversion isn't possible.
- *
- * This library does not yet make Dart objects usable from JavaScript, their
- * methods and proeprties are not accessible, though it does allow Dart
- * functions to be passed into and called from JavaScript.
- *
- * [JsObject] is the core type and represents a proxy of a JavaScript object.
- * JsObject gives access to the underlying JavaScript objects properties and
- * methods. `JsObject`s can be acquired by calls to JavaScript, or they can be
- * created from proxies to JavaScript constructors.
- *
- * The top-level getter [context] provides a [JsObject] that represents the
- * global object in JavaScript, usually `window`.
- *
- * The following example shows an alert dialog via a JavaScript call to the
- * global function `alert()`:
- *
- *     import 'dart:js';
- *
- *     main() => context.callMethod('alert', ['Hello from Dart!']);
- *
- * This example shows how to create a [JsObject] from a JavaScript constructor
- * and access its properties:
- *
- *     import 'dart:js';
- *
- *     main() {
- *       var object = new JsObject(context['Object']);
- *       object['greeting'] = 'Hello';
- *       object['greet'] = (name) => "${object['greeting']} $name";
- *       var message = object.callMethod('greet', ['JavaScript']);
- *       context['console'].callMethod('log', [message]);
- *     }
- *
- * ## Proxying and automatic conversion
- *
- * When setting properties on a JsObject or passing arguments to a Javascript
- * method or function, Dart objects are automatically converted or proxied to
- * JavaScript objects. When accessing JavaScript properties, or when a Dart
- * closure is invoked from JavaScript, the JavaScript objects are also
- * converted to Dart.
- *
- * Functions and closures are proxied in such a way that they are callable. A
- * Dart closure assigned to a JavaScript property is proxied by a function in
- * JavaScript. A JavaScript function accessed from Dart is proxied by a
- * [JsFunction], which has a [apply] method to invoke it.
- *
- * The following types are transferred directly and not proxied:
- *
- * * "Basic" types: `null`, `bool`, `num`, `String`, `DateTime`
- * * `Blob`
- * * `Event`
- * * `HtmlCollection`
- * * `ImageData`
- * * `KeyRange`
- * * `Node`
- * * `NodeList`
- * * `TypedData`, including its subclasses like `Int32List`, but _not_
- *   `ByteBuffer`
- * * `Window`
- *
- * ## Converting collections with JsObject.jsify()
- *
- * To create a JavaScript collection from a Dart collection use the
- * [JsObject.jsify] constructor, which converts Dart [Map]s and [Iterable]s
- * into JavaScript Objects and Arrays.
- *
- * The following expression creates a new JavaScript object with the properties
- * `a` and `b` defined:
- *
- *     var jsMap = new JsObject.jsify({'a': 1, 'b': 2});
- *
- * This expression creates a JavaScript array:
- *
- *     var jsArray = new JsObject.jsify([1, 2, 3]);
- */
+// DDC version of sdk/lib/js/dart2js/js_dart2js.dart
+
+/// Low-level support for interoperating with JavaScript.
+///
+/// You should usually use `package:js` instead of this library. For more
+/// information, see the [JS interop page](https://dart.dev/web/js-interop).
+///
+/// This library provides access to JavaScript objects from Dart, allowing
+/// Dart code to get and set properties, and call methods of JavaScript objects
+/// and invoke JavaScript functions. The library takes care of converting
+/// between Dart and JavaScript objects where possible, or providing proxies if
+/// conversion isn't possible.
+///
+/// This library does not make Dart objects usable from JavaScript, their
+/// methods and properties are not accessible, though it does allow Dart
+/// functions to be passed into and called from JavaScript.
+///
+/// [JsObject] is the core type and represents a proxy of a JavaScript object.
+/// JsObject gives access to the underlying JavaScript objects properties and
+/// methods. `JsObject`s can be acquired by calls to JavaScript, or they can be
+/// created from proxies to JavaScript constructors.
+///
+/// The top-level getter [context] provides a [JsObject] that represents the
+/// global object in JavaScript, usually `window`.
+///
+/// The following example shows an alert dialog via a JavaScript call to the
+/// global function `alert()`:
+///
+///     import 'dart:js';
+///
+///     main() => context.callMethod('alert', ['Hello from Dart!']);
+///
+/// This example shows how to create a [JsObject] from a JavaScript constructor
+/// and access its properties:
+///
+///     import 'dart:js';
+///
+///     main() {
+///       var object = JsObject(context['Object']);
+///       object['greeting'] = 'Hello';
+///       object['greet'] = (name) => "${object['greeting']} $name";
+///       var message = object.callMethod('greet', ['JavaScript']);
+///       context['console'].callMethod('log', [message]);
+///     }
+///
+/// ## Proxying and automatic conversion
+///
+/// When setting properties on a JsObject or passing arguments to a Javascript
+/// method or function, Dart objects are automatically converted or proxied to
+/// JavaScript objects. When accessing JavaScript properties, or when a Dart
+/// closure is invoked from JavaScript, the JavaScript objects are also
+/// converted to Dart.
+///
+/// Functions and closures are proxied in such a way that they are callable. A
+/// Dart closure assigned to a JavaScript property is proxied by a function in
+/// JavaScript. A JavaScript function accessed from Dart is proxied by a
+/// [JsFunction], which has a [apply] method to invoke it.
+///
+/// The following types are transferred directly and not proxied:
+///
+///   * Basic types: `null`, `bool`, `num`, `String`, `DateTime`
+///   * `TypedData`, including its subclasses like `Int32List`, but _not_
+///     `ByteBuffer`
+///   * When compiling for the web, also: `Blob`, `Event`, `ImageData`,
+///     `KeyRange`, `Node`, and `Window`.
+///
+/// ## Converting collections with JsObject.jsify()
+///
+/// To create a JavaScript collection from a Dart collection use the
+/// [JsObject.jsify] constructor, which converts Dart [Map]s and [Iterable]s
+/// into JavaScript Objects and Arrays.
+///
+/// The following expression creates a new JavaScript object with the properties
+/// `a` and `b` defined:
+///
+///     var jsMap = JsObject.jsify({'a': 1, 'b': 2});
+///
+/// This expression creates a JavaScript array:
+///
+///     var jsArray = JsObject.jsify([1, 2, 3]);
+///
+/// {@category Web}
 library dart.js;
 
 import 'dart:collection' show HashMap, ListMixin;
@@ -93,14 +92,13 @@
 import 'dart:_foreign_helper' show JS;
 import 'dart:_runtime' as dart;
 
+/// The JavaScript global object, usually `window`.
 final JsObject context = _wrapToDart(dart.global_);
 
-/**
- * Proxies a JavaScript object to Dart.
- *
- * The properties of the JavaScript object are accessible via the `[]` and
- * `[]=` operators. Methods are callable via [callMethod].
- */
+/// A proxy on a JavaScript object.
+///
+/// The properties of the JavaScript object are accessible via the `[]` and
+/// `[]=` operators. Methods are callable via [callMethod].
 class JsObject {
   // The wrapped JS object.
   final dynamic _jsObject;
@@ -110,10 +108,8 @@
     assert(_jsObject != null);
   }
 
-  /**
-   * Constructs a new JavaScript object from [constructor] and returns a proxy
-   * to it.
-   */
+  /// Constructs a JavaScript object from its native [constructor] and returns
+  /// a proxy to it.
   factory JsObject(JsFunction constructor, [List arguments]) {
     var ctor = constructor._jsObject;
     if (arguments == null) {
@@ -123,17 +119,15 @@
     return _wrapToDart(JS('', 'new #(...#)', ctor, unwrapped));
   }
 
-  /**
-   * Constructs a [JsObject] that proxies a native Dart object; _for expert use
-   * only_.
-   *
-   * Use this constructor only if you wish to get access to JavaScript
-   * properties attached to a browser host object, such as a Node or Blob, that
-   * is normally automatically converted into a native Dart object.
-   *
-   * An exception will be thrown if [object] either is `null` or has the type
-   * `bool`, `num`, or `String`.
-   */
+  /// Constructs a [JsObject] that proxies a native Dart object; _for expert use
+  /// only_.
+  ///
+  /// Use this constructor only if you wish to get access to JavaScript
+  /// properties attached to a browser host object, such as a Node or Blob, that
+  /// is normally automatically converted into a native Dart object.
+  ///
+  /// An exception will be thrown if [object] either is `null` or has the type
+  /// `bool`, `num`, or `String`.
   factory JsObject.fromBrowserObject(object) {
     if (object is num || object is String || object is bool || object == null) {
       throw ArgumentError("object cannot be a num, string, bool, or null");
@@ -141,15 +135,13 @@
     return _wrapToDart(_convertToJS(object));
   }
 
-  /**
-   * Recursively converts a JSON-like collection of Dart objects to a
-   * collection of JavaScript objects and returns a [JsObject] proxy to it.
-   *
-   * [object] must be a [Map] or [Iterable], the contents of which are also
-   * converted. Maps and Iterables are copied to a new JavaScript object.
-   * Primitives and other transferable values are directly converted to their
-   * JavaScript type, and all other objects are proxied.
-   */
+  /// Recursively converts a JSON-like collection of Dart objects to a
+  /// collection of JavaScript objects and returns a [JsObject] proxy to it.
+  ///
+  /// [object] must be a [Map] or [Iterable], the contents of which are also
+  /// converted. Maps and Iterables are copied to a new JavaScript object.
+  /// Primitives and other transferable values are directly converted to their
+  /// JavaScript type, and all other objects are proxied.
   factory JsObject.jsify(object) {
     if ((object is! Map) && (object is! Iterable)) {
       throw ArgumentError("object must be a Map or Iterable");
@@ -184,12 +176,10 @@
     return _convert(data);
   }
 
-  /**
-   * Returns the value associated with [property] from the proxied JavaScript
-   * object.
-   *
-   * The type of [property] must be either [String] or [num].
-   */
+  /// Returns the value associated with [property] from the proxied JavaScript
+  /// object.
+  ///
+  /// The type of [property] must be either [String] or [num].
   dynamic operator [](Object property) {
     if (property is! String && property is! num) {
       throw ArgumentError("property is not a String or num");
@@ -197,12 +187,10 @@
     return _convertToDart(JS('', '#[#]', _jsObject, property));
   }
 
-  /**
-   * Sets the value associated with [property] on the proxied JavaScript
-   * object.
-   *
-   * The type of [property] must be either [String] or [num].
-   */
+  // Sets the value associated with [property] on the proxied JavaScript
+  // object.
+  //
+  // The type of [property] must be either [String] or [num].
   void operator []=(Object property, value) {
     if (property is! String && property is! num) {
       throw ArgumentError("property is not a String or num");
@@ -215,12 +203,10 @@
   bool operator ==(other) =>
       other is JsObject && JS<bool>('!', '# === #', _jsObject, other._jsObject);
 
-  /**
-   * Returns `true` if the JavaScript object contains the specified property
-   * either directly or though its prototype chain.
-   *
-   * This is the equivalent of the `in` operator in JavaScript.
-   */
+  /// Returns `true` if the JavaScript object contains the specified property
+  /// either directly or though its prototype chain.
+  ///
+  /// This is the equivalent of the `in` operator in JavaScript.
   bool hasProperty(property) {
     if (property is! String && property is! num) {
       throw ArgumentError("property is not a String or num");
@@ -228,11 +214,9 @@
     return JS<bool>('!', '# in #', property, _jsObject);
   }
 
-  /**
-   * Removes [property] from the JavaScript object.
-   *
-   * This is the equivalent of the `delete` operator in JavaScript.
-   */
+  /// Removes [property] from the JavaScript object.
+  ///
+  /// This is the equivalent of the `delete` operator in JavaScript.
   void deleteProperty(property) {
     if (property is! String && property is! num) {
       throw ArgumentError("property is not a String or num");
@@ -240,18 +224,14 @@
     JS<bool>('!', 'delete #[#]', _jsObject, property);
   }
 
-  /**
-   * Returns `true` if the JavaScript object has [type] in its prototype chain.
-   *
-   * This is the equivalent of the `instanceof` operator in JavaScript.
-   */
+  /// Returns `true` if the JavaScript object has [type] in its prototype chain.
+  ///
+  /// This is the equivalent of the `instanceof` operator in JavaScript.
   bool instanceof(JsFunction type) {
     return JS<bool>('!', '# instanceof #', _jsObject, _convertToJS(type));
   }
 
-  /**
-   * Returns the result of the JavaScript objects `toString` method.
-   */
+  /// Returns the result of the JavaScript objects `toString` method.
   String toString() {
     try {
       return JS<String>('!', 'String(#)', _jsObject);
@@ -260,12 +240,10 @@
     }
   }
 
-  /**
-   * Calls [method] on the JavaScript object with the arguments [args] and
-   * returns the result.
-   *
-   * The type of [method] must be either [String] or [num].
-   */
+  /// Calls [method] on the JavaScript object with the arguments [args] and
+  /// returns the result.
+  ///
+  /// The type of [method] must be either [String] or [num].
   dynamic callMethod(method, [List args]) {
     if (method is! String && method is! num) {
       throw ArgumentError("method is not a String or num");
@@ -279,14 +257,10 @@
   }
 }
 
-/**
- * Proxies a JavaScript Function object.
- */
+/// A proxy on a JavaScript Function object.
 class JsFunction extends JsObject {
-  /**
-   * Returns a [JsFunction] that captures its 'this' binding and calls [f]
-   * with the value of this passed as the first argument.
-   */
+  /// Returns a [JsFunction] that captures its 'this' binding and calls [f]
+  /// with the value of JavaScript `this` passed as the first argument.
   factory JsFunction.withThis(Function f) {
     return JsFunction._fromJs(JS(
         '',
@@ -305,10 +279,8 @@
 
   JsFunction._fromJs(jsObject) : super._fromJs(jsObject);
 
-  /**
-   * Invokes the JavaScript function with arguments [args]. If [thisArg] is
-   * supplied it is the value of `this` for the invocation.
-   */
+  /// Invokes the JavaScript function with arguments [args]. If [thisArg] is
+  /// supplied it is the value of `this` for the invocation.
   dynamic apply(List args, {thisArg}) => _convertToDart(JS(
       '',
       '#.apply(#, #)',
@@ -318,17 +290,13 @@
 }
 
 // TODO(jmesserly): this is totally unnecessary in dev_compiler.
-/** A [List] that proxies a JavaScript array. */
+/// A [List] that proxies a JavaScript array.
 class JsArray<E> extends JsObject with ListMixin<E> {
-  /**
-   * Creates a new JavaScript array.
-   */
+  /// Creates an empty JavaScript array.
   JsArray() : super._fromJs([]);
 
-  /**
-   * Creates a new JavaScript array and initializes it to the contents of
-   * [other].
-   */
+  /// Creates a new JavaScript array and initializes it to the contents of
+  /// [other].
   JsArray.from(Iterable<E> other)
       : super._fromJs([]..addAll(other.map(_convertToJS)));
 
@@ -544,16 +512,16 @@
 Expando<Function> _interopExpando = Expando<Function>();
 
 /// Returns a wrapper around function [f] that can be called from JavaScript
-/// using the package:js Dart-JavaScript interop.
+/// using `package:js` JavaScript interop.
 ///
-/// For performance reasons in Dart2Js, by default Dart functions cannot be
-/// passed directly to JavaScript unless this method is called to create
-/// a Function compatible with both Dart and JavaScript.
-/// Calling this method repeatedly on a function will return the same function.
-/// The [Function] returned by this method can be used from both Dart and
-/// JavaScript. We may remove the need to call this method completely in the
-/// future if Dart2Js is refactored so that its function calling conventions
-/// are more compatible with JavaScript.
+/// The calling conventions in Dart2Js differ from JavaScript and so, by
+/// default, it is not possible to call a Dart function directly. Wrapping with
+/// `allowInterop` creates a function that can be called from JavaScript or
+/// Dart. The semantics of the wrapped function are still more strict than
+/// JavaScript, and the function will throw if called with too many or too few
+/// arguments.
+///
+/// Calling this method repeatedly on a function will return the same result.
 F allowInterop<F extends Function>(F f) {
   var ret = _interopExpando[f];
   if (ret == null) {
@@ -571,12 +539,13 @@
 
 Expando<Function> _interopCaptureThisExpando = Expando<Function>();
 
-/// Returns a [Function] that when called from JavaScript captures its 'this'
-/// binding and calls [f] with the value of this passed as the first argument.
-/// When called from Dart, [null] will be passed as the first argument.
+/// Returns a wrapper around function [f] that can be called from JavaScript
+/// using `package:js` JavaScript interop, passing JavaScript `this` as the first
+/// argument.
 ///
-/// See the documentation for [allowInterop]. This method should only be used
-/// with package:js Dart-JavaScript interop.
+/// See [allowInterop].
+///
+/// When called from Dart, [null] will be passed as the first argument.
 Function allowInteropCaptureThis(Function f) {
   var ret = _interopCaptureThisExpando[f];
   if (ret == null) {
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 8c167115..a1187f6 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -366,7 +366,7 @@
         list.add(createRuntimeType(_arguments[start + index]));
       }
     }
-    return list;
+    return JSArray.markUnmodifiableList(list);
   }
 
   List get positionalArguments {
diff --git a/sdk/lib/_internal/js_runtime/lib/rti.dart b/sdk/lib/_internal/js_runtime/lib/rti.dart
index f7ca527..780f6c0 100644
--- a/sdk/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/rti.dart
@@ -2147,11 +2147,16 @@
     }
   }
 
+  // TODO(fishythefish): Disallow JavaScriptFunction as a subtype of function
+  // types using features inaccessible from JavaScript.
+
   if (isGenericFunctionKind(t)) {
+    if (isJsFunctionType(s)) return true;
     return _isGenericFunctionSubtype(universe, s, sEnv, t, tEnv);
   }
 
   if (isFunctionKind(t)) {
+    if (isJsFunctionType(s)) return true;
     return _isFunctionSubtype(universe, s, sEnv, t, tEnv);
   }
 
@@ -2398,6 +2403,11 @@
     Rti._getKind(t) == Rti.kindInterface &&
     Rti._getInterfaceName(t) == JS_GET_NAME(JsGetName.FUNCTION_CLASS_TYPE_NAME);
 
+bool isJsFunctionType(Rti t) =>
+    Rti._getKind(t) == Rti.kindInterface &&
+    Rti._getInterfaceName(t) ==
+        JS_GET_NAME(JsGetName.JS_FUNCTION_CLASS_TYPE_NAME);
+
 /// Unchecked cast to Rti.
 Rti _castToRti(s) => JS('Rti', '#', s);
 
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 50cf7e8..6800e37 100644
--- a/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart
+++ b/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart
@@ -326,6 +326,9 @@
   /// String representation of the type of the function class.
   FUNCTION_CLASS_TYPE_NAME,
 
+  /// String representation of the type of the JavaScriptFunction class.
+  JS_FUNCTION_CLASS_TYPE_NAME,
+
   /// String recipe for the [bool] type.
   BOOL_RECIPE,
 
diff --git a/runtime/bin/builtin.dart b/sdk/lib/_internal/vm/bin/builtin.dart
similarity index 100%
rename from runtime/bin/builtin.dart
rename to sdk/lib/_internal/vm/bin/builtin.dart
diff --git a/runtime/bin/cli_patch.dart b/sdk/lib/_internal/vm/bin/cli_patch.dart
similarity index 100%
rename from runtime/bin/cli_patch.dart
rename to sdk/lib/_internal/vm/bin/cli_patch.dart
diff --git a/runtime/bin/common_patch.dart b/sdk/lib/_internal/vm/bin/common_patch.dart
similarity index 100%
rename from runtime/bin/common_patch.dart
rename to sdk/lib/_internal/vm/bin/common_patch.dart
diff --git a/runtime/bin/directory_patch.dart b/sdk/lib/_internal/vm/bin/directory_patch.dart
similarity index 100%
rename from runtime/bin/directory_patch.dart
rename to sdk/lib/_internal/vm/bin/directory_patch.dart
diff --git a/runtime/bin/eventhandler_patch.dart b/sdk/lib/_internal/vm/bin/eventhandler_patch.dart
similarity index 100%
rename from runtime/bin/eventhandler_patch.dart
rename to sdk/lib/_internal/vm/bin/eventhandler_patch.dart
diff --git a/runtime/bin/file_patch.dart b/sdk/lib/_internal/vm/bin/file_patch.dart
similarity index 100%
rename from runtime/bin/file_patch.dart
rename to sdk/lib/_internal/vm/bin/file_patch.dart
diff --git a/runtime/bin/file_system_entity_patch.dart b/sdk/lib/_internal/vm/bin/file_system_entity_patch.dart
similarity index 100%
rename from runtime/bin/file_system_entity_patch.dart
rename to sdk/lib/_internal/vm/bin/file_system_entity_patch.dart
diff --git a/runtime/bin/filter_patch.dart b/sdk/lib/_internal/vm/bin/filter_patch.dart
similarity index 100%
rename from runtime/bin/filter_patch.dart
rename to sdk/lib/_internal/vm/bin/filter_patch.dart
diff --git a/runtime/bin/io_service_patch.dart b/sdk/lib/_internal/vm/bin/io_service_patch.dart
similarity index 100%
rename from runtime/bin/io_service_patch.dart
rename to sdk/lib/_internal/vm/bin/io_service_patch.dart
diff --git a/runtime/bin/namespace_patch.dart b/sdk/lib/_internal/vm/bin/namespace_patch.dart
similarity index 100%
rename from runtime/bin/namespace_patch.dart
rename to sdk/lib/_internal/vm/bin/namespace_patch.dart
diff --git a/runtime/bin/platform_patch.dart b/sdk/lib/_internal/vm/bin/platform_patch.dart
similarity index 100%
rename from runtime/bin/platform_patch.dart
rename to sdk/lib/_internal/vm/bin/platform_patch.dart
diff --git a/runtime/bin/process_patch.dart b/sdk/lib/_internal/vm/bin/process_patch.dart
similarity index 100%
rename from runtime/bin/process_patch.dart
rename to sdk/lib/_internal/vm/bin/process_patch.dart
diff --git a/runtime/bin/secure_socket_patch.dart b/sdk/lib/_internal/vm/bin/secure_socket_patch.dart
similarity index 100%
rename from runtime/bin/secure_socket_patch.dart
rename to sdk/lib/_internal/vm/bin/secure_socket_patch.dart
diff --git a/runtime/bin/socket_patch.dart b/sdk/lib/_internal/vm/bin/socket_patch.dart
similarity index 100%
rename from runtime/bin/socket_patch.dart
rename to sdk/lib/_internal/vm/bin/socket_patch.dart
diff --git a/runtime/bin/stdio_patch.dart b/sdk/lib/_internal/vm/bin/stdio_patch.dart
similarity index 100%
rename from runtime/bin/stdio_patch.dart
rename to sdk/lib/_internal/vm/bin/stdio_patch.dart
diff --git a/runtime/bin/sync_socket_patch.dart b/sdk/lib/_internal/vm/bin/sync_socket_patch.dart
similarity index 100%
rename from runtime/bin/sync_socket_patch.dart
rename to sdk/lib/_internal/vm/bin/sync_socket_patch.dart
diff --git a/runtime/lib/array.dart b/sdk/lib/_internal/vm/lib/array.dart
similarity index 100%
rename from runtime/lib/array.dart
rename to sdk/lib/_internal/vm/lib/array.dart
diff --git a/runtime/lib/array_patch.dart b/sdk/lib/_internal/vm/lib/array_patch.dart
similarity index 100%
rename from runtime/lib/array_patch.dart
rename to sdk/lib/_internal/vm/lib/array_patch.dart
diff --git a/runtime/lib/async_patch.dart b/sdk/lib/_internal/vm/lib/async_patch.dart
similarity index 100%
rename from runtime/lib/async_patch.dart
rename to sdk/lib/_internal/vm/lib/async_patch.dart
diff --git a/runtime/lib/bigint_patch.dart b/sdk/lib/_internal/vm/lib/bigint_patch.dart
similarity index 100%
rename from runtime/lib/bigint_patch.dart
rename to sdk/lib/_internal/vm/lib/bigint_patch.dart
diff --git a/runtime/lib/bool_patch.dart b/sdk/lib/_internal/vm/lib/bool_patch.dart
similarity index 100%
rename from runtime/lib/bool_patch.dart
rename to sdk/lib/_internal/vm/lib/bool_patch.dart
diff --git a/runtime/lib/class_id.dart b/sdk/lib/_internal/vm/lib/class_id.dart
similarity index 100%
rename from runtime/lib/class_id.dart
rename to sdk/lib/_internal/vm/lib/class_id.dart
diff --git a/runtime/lib/class_id_fasta.dart b/sdk/lib/_internal/vm/lib/class_id_fasta.dart
similarity index 100%
rename from runtime/lib/class_id_fasta.dart
rename to sdk/lib/_internal/vm/lib/class_id_fasta.dart
diff --git a/runtime/lib/collection_patch.dart b/sdk/lib/_internal/vm/lib/collection_patch.dart
similarity index 100%
rename from runtime/lib/collection_patch.dart
rename to sdk/lib/_internal/vm/lib/collection_patch.dart
diff --git a/runtime/lib/compact_hash.dart b/sdk/lib/_internal/vm/lib/compact_hash.dart
similarity index 100%
rename from runtime/lib/compact_hash.dart
rename to sdk/lib/_internal/vm/lib/compact_hash.dart
diff --git a/runtime/lib/convert_patch.dart b/sdk/lib/_internal/vm/lib/convert_patch.dart
similarity index 100%
rename from runtime/lib/convert_patch.dart
rename to sdk/lib/_internal/vm/lib/convert_patch.dart
diff --git a/runtime/lib/core_patch.dart b/sdk/lib/_internal/vm/lib/core_patch.dart
similarity index 100%
rename from runtime/lib/core_patch.dart
rename to sdk/lib/_internal/vm/lib/core_patch.dart
diff --git a/runtime/lib/date_patch.dart b/sdk/lib/_internal/vm/lib/date_patch.dart
similarity index 100%
rename from runtime/lib/date_patch.dart
rename to sdk/lib/_internal/vm/lib/date_patch.dart
diff --git a/runtime/lib/deferred_load_patch.dart b/sdk/lib/_internal/vm/lib/deferred_load_patch.dart
similarity index 100%
rename from runtime/lib/deferred_load_patch.dart
rename to sdk/lib/_internal/vm/lib/deferred_load_patch.dart
diff --git a/runtime/lib/developer.dart b/sdk/lib/_internal/vm/lib/developer.dart
similarity index 100%
rename from runtime/lib/developer.dart
rename to sdk/lib/_internal/vm/lib/developer.dart
diff --git a/runtime/lib/double.dart b/sdk/lib/_internal/vm/lib/double.dart
similarity index 100%
rename from runtime/lib/double.dart
rename to sdk/lib/_internal/vm/lib/double.dart
diff --git a/runtime/lib/double_patch.dart b/sdk/lib/_internal/vm/lib/double_patch.dart
similarity index 100%
rename from runtime/lib/double_patch.dart
rename to sdk/lib/_internal/vm/lib/double_patch.dart
diff --git a/runtime/lib/empty_source.dart b/sdk/lib/_internal/vm/lib/empty_source.dart
similarity index 100%
rename from runtime/lib/empty_source.dart
rename to sdk/lib/_internal/vm/lib/empty_source.dart
diff --git a/runtime/lib/errors_patch.dart b/sdk/lib/_internal/vm/lib/errors_patch.dart
similarity index 100%
rename from runtime/lib/errors_patch.dart
rename to sdk/lib/_internal/vm/lib/errors_patch.dart
diff --git a/runtime/lib/expando_patch.dart b/sdk/lib/_internal/vm/lib/expando_patch.dart
similarity index 100%
rename from runtime/lib/expando_patch.dart
rename to sdk/lib/_internal/vm/lib/expando_patch.dart
diff --git a/runtime/lib/ffi_dynamic_library_patch.dart b/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart
similarity index 100%
rename from runtime/lib/ffi_dynamic_library_patch.dart
rename to sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart
diff --git a/runtime/lib/ffi_native_type_patch.dart b/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart
similarity index 100%
rename from runtime/lib/ffi_native_type_patch.dart
rename to sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart
diff --git a/runtime/lib/ffi_patch.dart b/sdk/lib/_internal/vm/lib/ffi_patch.dart
similarity index 100%
rename from runtime/lib/ffi_patch.dart
rename to sdk/lib/_internal/vm/lib/ffi_patch.dart
diff --git a/runtime/lib/function.dart b/sdk/lib/_internal/vm/lib/function.dart
similarity index 100%
rename from runtime/lib/function.dart
rename to sdk/lib/_internal/vm/lib/function.dart
diff --git a/runtime/lib/function_patch.dart b/sdk/lib/_internal/vm/lib/function_patch.dart
similarity index 100%
rename from runtime/lib/function_patch.dart
rename to sdk/lib/_internal/vm/lib/function_patch.dart
diff --git a/runtime/lib/growable_array.dart b/sdk/lib/_internal/vm/lib/growable_array.dart
similarity index 100%
rename from runtime/lib/growable_array.dart
rename to sdk/lib/_internal/vm/lib/growable_array.dart
diff --git a/runtime/lib/identical_patch.dart b/sdk/lib/_internal/vm/lib/identical_patch.dart
similarity index 100%
rename from runtime/lib/identical_patch.dart
rename to sdk/lib/_internal/vm/lib/identical_patch.dart
diff --git a/runtime/lib/immutable_map.dart b/sdk/lib/_internal/vm/lib/immutable_map.dart
similarity index 100%
rename from runtime/lib/immutable_map.dart
rename to sdk/lib/_internal/vm/lib/immutable_map.dart
diff --git a/runtime/lib/integers.dart b/sdk/lib/_internal/vm/lib/integers.dart
similarity index 100%
rename from runtime/lib/integers.dart
rename to sdk/lib/_internal/vm/lib/integers.dart
diff --git a/runtime/lib/integers_patch.dart b/sdk/lib/_internal/vm/lib/integers_patch.dart
similarity index 100%
rename from runtime/lib/integers_patch.dart
rename to sdk/lib/_internal/vm/lib/integers_patch.dart
diff --git a/runtime/lib/internal_patch.dart b/sdk/lib/_internal/vm/lib/internal_patch.dart
similarity index 100%
rename from runtime/lib/internal_patch.dart
rename to sdk/lib/_internal/vm/lib/internal_patch.dart
diff --git a/runtime/lib/invocation_mirror_patch.dart b/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart
similarity index 100%
rename from runtime/lib/invocation_mirror_patch.dart
rename to sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart
diff --git a/runtime/lib/isolate_patch.dart b/sdk/lib/_internal/vm/lib/isolate_patch.dart
similarity index 100%
rename from runtime/lib/isolate_patch.dart
rename to sdk/lib/_internal/vm/lib/isolate_patch.dart
diff --git a/runtime/lib/lib_prefix.dart b/sdk/lib/_internal/vm/lib/lib_prefix.dart
similarity index 100%
rename from runtime/lib/lib_prefix.dart
rename to sdk/lib/_internal/vm/lib/lib_prefix.dart
diff --git a/runtime/lib/map_patch.dart b/sdk/lib/_internal/vm/lib/map_patch.dart
similarity index 100%
rename from runtime/lib/map_patch.dart
rename to sdk/lib/_internal/vm/lib/map_patch.dart
diff --git a/runtime/lib/math_patch.dart b/sdk/lib/_internal/vm/lib/math_patch.dart
similarity index 100%
rename from runtime/lib/math_patch.dart
rename to sdk/lib/_internal/vm/lib/math_patch.dart
diff --git a/runtime/lib/mirror_reference.dart b/sdk/lib/_internal/vm/lib/mirror_reference.dart
similarity index 100%
rename from runtime/lib/mirror_reference.dart
rename to sdk/lib/_internal/vm/lib/mirror_reference.dart
diff --git a/runtime/lib/mirrors_impl.dart b/sdk/lib/_internal/vm/lib/mirrors_impl.dart
similarity index 90%
copy from runtime/lib/mirrors_impl.dart
copy to sdk/lib/_internal/vm/lib/mirrors_impl.dart
index d6d07fd..013246c 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/sdk/lib/_internal/vm/lib/mirrors_impl.dart
@@ -67,7 +67,7 @@
 
 bool _subtypeTest(Type a, Type b) native 'TypeMirror_subtypeTest';
 
-class _LocalMirrorSystem extends MirrorSystem {
+class _MirrorSystem extends MirrorSystem {
   final TypeMirror dynamicType = new _SpecialTypeMirror._('dynamic');
   final TypeMirror voidType = new _SpecialTypeMirror._('void');
 
@@ -114,13 +114,11 @@
   }
 }
 
-abstract class _LocalMirror implements Mirror {}
-
-class _LocalIsolateMirror extends _LocalMirror implements IsolateMirror {
+class _IsolateMirror extends Mirror implements IsolateMirror {
   final String debugName;
   final LibraryMirror rootLibrary;
 
-  _LocalIsolateMirror._(this.debugName, this.rootLibrary);
+  _IsolateMirror._(this.debugName, this.rootLibrary);
 
   bool get isCurrent => true;
 
@@ -201,14 +199,14 @@
   List<InstanceMirror> get metadata => const <InstanceMirror>[];
 }
 
-abstract class _LocalObjectMirror extends _LocalMirror implements ObjectMirror {
+abstract class _ObjectMirror extends Mirror implements ObjectMirror {
   _invoke(reflectee, functionName, arguments, argumentNames);
   _invokeGetter(reflectee, getterName);
   _invokeSetter(reflectee, setterName, value);
 
   final _reflectee; // May be a MirrorReference or an ordinary object.
 
-  _LocalObjectMirror._(this._reflectee);
+  _ObjectMirror._(this._reflectee);
 
   InstanceMirror invoke(Symbol memberName, List positionalArguments,
       [Map<Symbol, dynamic> namedArguments]) {
@@ -260,9 +258,8 @@
   }
 }
 
-class _LocalInstanceMirror extends _LocalObjectMirror
-    implements InstanceMirror {
-  _LocalInstanceMirror._(reflectee) : super._(reflectee);
+class _InstanceMirror extends _ObjectMirror implements InstanceMirror {
+  _InstanceMirror._(reflectee) : super._(reflectee);
 
   ClassMirror _type;
   ClassMirror get type {
@@ -282,8 +279,7 @@
   String toString() => 'InstanceMirror on ${Error.safeToString(_reflectee)}';
 
   bool operator ==(other) {
-    return other is _LocalInstanceMirror &&
-        identical(_reflectee, other._reflectee);
+    return other is _InstanceMirror && identical(_reflectee, other._reflectee);
   }
 
   int get hashCode {
@@ -334,9 +330,8 @@
   static _computeType(reflectee) native 'InstanceMirror_computeType';
 }
 
-class _LocalClosureMirror extends _LocalInstanceMirror
-    implements ClosureMirror {
-  _LocalClosureMirror._(reflectee) : super._(reflectee);
+class _ClosureMirror extends _InstanceMirror implements ClosureMirror {
+  _ClosureMirror._(reflectee) : super._(reflectee);
 
   MethodMirror _function;
   MethodMirror get function {
@@ -356,12 +351,11 @@
   static _computeFunction(reflectee) native 'ClosureMirror_function';
 }
 
-abstract class _LocalTypeMirror {
+abstract class _TypeMirror {
   Type get _reflectedType;
 }
 
-class _LocalClassMirror extends _LocalObjectMirror
-    implements ClassMirror, _LocalTypeMirror {
+class _ClassMirror extends _ObjectMirror implements ClassMirror, _TypeMirror {
   final Type _reflectedType;
   Symbol _simpleName;
   DeclarationMirror _owner;
@@ -377,7 +371,7 @@
   final bool isEnum;
   Type _instantiator;
 
-  _LocalClassMirror._(
+  _ClassMirror._(
       reflectee,
       reflectedType,
       String simpleName,
@@ -419,7 +413,7 @@
 
   DeclarationMirror get owner {
     if (_owner == null) {
-      var uri = _LocalClassMirror._libraryUri(_reflectee);
+      var uri = _ClassMirror._libraryUri(_reflectee);
       _owner = currentMirrorSystem().libraries[Uri.parse(uri)];
     }
     return _owner;
@@ -433,8 +427,8 @@
     return _location(_reflectee);
   }
 
-  _LocalClassMirror _trueSuperclassField;
-  _LocalClassMirror get _trueSuperclass {
+  _ClassMirror _trueSuperclassField;
+  _ClassMirror get _trueSuperclass {
     if (_trueSuperclassField == null) {
       Type supertype = isOriginalDeclaration
           ? _supertype(_reflectedType)
@@ -487,8 +481,7 @@
   var _mixin;
   ClassMirror get mixin {
     if (_mixin == null) {
-      Type mixinType =
-          _nativeMixinInstantiated(_reflectedType, _instantiator);
+      Type mixinType = _nativeMixinInstantiated(_reflectedType, _instantiator);
       if (mixinType == null) {
         // The reflectee is not a mixin application.
         _mixin = this;
@@ -599,7 +592,7 @@
       ClassMirror owner = originalDeclaration;
       var mirror;
       for (var i = 0; i < params.length; i += 2) {
-        mirror = new _LocalTypeVariableMirror._(params[i + 1], params[i], owner);
+        mirror = new _TypeVariableMirror._(params[i + 1], params[i], owner);
         _typeVariables.add(mirror);
       }
       _typeVariables =
@@ -676,14 +669,13 @@
   bool isSubtypeOf(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
     if (other == currentMirrorSystem().voidType) return false;
-    return _subtypeTest(
-        _reflectedType, (other as _LocalTypeMirror)._reflectedType);
+    return _subtypeTest(_reflectedType, (other as _TypeMirror)._reflectedType);
   }
 
   bool isAssignableTo(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
     if (other == currentMirrorSystem().voidType) return false;
-    final otherReflectedType = (other as _LocalTypeMirror)._reflectedType;
+    final otherReflectedType = (other as _TypeMirror)._reflectedType;
     return _subtypeTest(_reflectedType, otherReflectedType) ||
         _subtypeTest(otherReflectedType, _reflectedType);
   }
@@ -741,12 +733,11 @@
       native "ClassMirror_type_arguments";
 }
 
-class _LocalFunctionTypeMirror extends _LocalClassMirror
-    implements FunctionTypeMirror {
+class _FunctionTypeMirror extends _ClassMirror implements FunctionTypeMirror {
   final _functionReflectee;
-  _LocalFunctionTypeMirror._(reflectee, this._functionReflectee, reflectedType)
-      : super._(reflectee, reflectedType, null, null, false, false, false, false,
-            false);
+  _FunctionTypeMirror._(reflectee, this._functionReflectee, reflectedType)
+      : super._(reflectee, reflectedType, null, null, false, false, false,
+            false, false);
 
   bool get _isAnonymousMixinApplication => false;
 
@@ -805,12 +796,11 @@
       native "FunctionTypeMirror_parameters";
 }
 
-abstract class _LocalDeclarationMirror extends _LocalMirror
-    implements DeclarationMirror {
+abstract class _DeclarationMirror extends Mirror implements DeclarationMirror {
   final _reflectee;
   Symbol _simpleName;
 
-  _LocalDeclarationMirror._(this._reflectee, this._simpleName);
+  _DeclarationMirror._(this._reflectee, this._simpleName);
 
   Symbol get simpleName => _simpleName;
 
@@ -843,9 +833,9 @@
   int get hashCode => simpleName.hashCode;
 }
 
-class _LocalTypeVariableMirror extends _LocalDeclarationMirror
-    implements TypeVariableMirror, _LocalTypeMirror {
-  _LocalTypeVariableMirror._(reflectee, String simpleName, this._owner)
+class _TypeVariableMirror extends _DeclarationMirror
+    implements TypeVariableMirror, _TypeMirror {
+  _TypeVariableMirror._(reflectee, String simpleName, this._owner)
       : super._(reflectee, _s(simpleName));
 
   DeclarationMirror _owner;
@@ -894,14 +884,13 @@
   bool isSubtypeOf(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
     if (other == currentMirrorSystem().voidType) return false;
-    return _subtypeTest(
-        _reflectedType, (other as _LocalTypeMirror)._reflectedType);
+    return _subtypeTest(_reflectedType, (other as _TypeMirror)._reflectedType);
   }
 
   bool isAssignableTo(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
     if (other == currentMirrorSystem().voidType) return false;
-    final otherReflectedType = (other as _LocalTypeMirror)._reflectedType;
+    final otherReflectedType = (other as _TypeMirror)._reflectedType;
     return _subtypeTest(_reflectedType, otherReflectedType) ||
         _subtypeTest(otherReflectedType, _reflectedType);
   }
@@ -913,13 +902,13 @@
       native "TypeVariableMirror_upper_bound";
 }
 
-class _LocalTypedefMirror extends _LocalDeclarationMirror
-    implements TypedefMirror, _LocalTypeMirror {
+class _TypedefMirror extends _DeclarationMirror
+    implements TypedefMirror, _TypeMirror {
   final Type _reflectedType;
   final bool _isGeneric;
   final bool _isGenericDeclaration;
 
-  _LocalTypedefMirror(reflectee, this._reflectedType, String simpleName,
+  _TypedefMirror(reflectee, this._reflectedType, String simpleName,
       this._isGeneric, this._isGenericDeclaration, this._owner)
       : super._(reflectee, _s(simpleName));
 
@@ -928,13 +917,13 @@
   DeclarationMirror _owner;
   DeclarationMirror get owner {
     if (_owner == null) {
-      var uri = _LocalClassMirror._libraryUri(_reflectee);
+      var uri = _ClassMirror._libraryUri(_reflectee);
       _owner = currentMirrorSystem().libraries[Uri.parse(uri)];
     }
     return _owner;
   }
 
-  _LocalFunctionTypeMirror _referent;
+  _FunctionTypeMirror _referent;
   FunctionTypeMirror get referent {
     if (_referent == null) {
       _referent = _nativeReferent(_reflectedType);
@@ -966,11 +955,11 @@
   List<TypeVariableMirror> get typeVariables {
     if (_typeVariables == null) {
       _typeVariables = new List<TypeVariableMirror>();
-      List params = _LocalClassMirror._ClassMirror_type_variables(_reflectee);
+      List params = _ClassMirror._ClassMirror_type_variables(_reflectee);
       TypedefMirror owner = originalDeclaration;
       var mirror;
       for (var i = 0; i < params.length; i += 2) {
-        mirror = new _LocalTypeVariableMirror._(params[i + 1], params[i], owner);
+        mirror = new _TypeVariableMirror._(params[i + 1], params[i], owner);
         _typeVariables.add(mirror);
       }
     }
@@ -983,9 +972,9 @@
       if (_isGenericDeclaration) {
         _typeArguments = const <TypeMirror>[];
       } else {
-        _typeArguments = new UnmodifiableListView<TypeMirror>(_LocalClassMirror
-            ._computeTypeArguments(_reflectedType)
-            .cast<TypeMirror>());
+        _typeArguments = new UnmodifiableListView<TypeMirror>(
+            _ClassMirror._computeTypeArguments(_reflectedType)
+                .cast<TypeMirror>());
       }
     }
     return _typeArguments;
@@ -996,14 +985,13 @@
   bool isSubtypeOf(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
     if (other == currentMirrorSystem().voidType) return false;
-    return _subtypeTest(
-        _reflectedType, (other as _LocalTypeMirror)._reflectedType);
+    return _subtypeTest(_reflectedType, (other as _TypeMirror)._reflectedType);
   }
 
   bool isAssignableTo(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
     if (other == currentMirrorSystem().voidType) return false;
-    final otherReflectedType = (other as _LocalTypeMirror)._reflectedType;
+    final otherReflectedType = (other as _TypeMirror)._reflectedType;
     return _subtypeTest(_reflectedType, otherReflectedType) ||
         _subtypeTest(otherReflectedType, _reflectedType);
   }
@@ -1020,11 +1008,11 @@
   return MirrorSystem.getSymbol('${unwrapped}=', library);
 }
 
-class _LocalLibraryMirror extends _LocalObjectMirror implements LibraryMirror {
+class _LibraryMirror extends _ObjectMirror implements LibraryMirror {
   final Symbol simpleName;
   final Uri uri;
 
-  _LocalLibraryMirror._(reflectee, String simpleName, String url)
+  _LibraryMirror._(reflectee, String simpleName, String url)
       : this.simpleName = _s(simpleName),
         this.uri = Uri.parse(url),
         super._(reflectee);
@@ -1097,7 +1085,7 @@
   List<dynamic> _computeMembers(reflectee) native "LibraryMirror_members";
 }
 
-class _LocalLibraryDependencyMirror extends _LocalMirror
+class _LibraryDependencyMirror extends Mirror
     implements LibraryDependencyMirror {
   final LibraryMirror sourceLibrary;
   var _targetMirrorOrPrefix;
@@ -1107,7 +1095,7 @@
   final bool isDeferred;
   final List<InstanceMirror> metadata;
 
-  _LocalLibraryDependencyMirror._(
+  _LibraryDependencyMirror._(
       this.sourceLibrary,
       this._targetMirrorOrPrefix,
       List<dynamic> mutableCombinators,
@@ -1124,7 +1112,7 @@
   bool get isExport => !isImport;
 
   LibraryMirror get targetLibrary {
-    if (_targetMirrorOrPrefix is _LocalLibraryMirror) {
+    if (_targetMirrorOrPrefix is _LibraryMirror) {
       return _targetMirrorOrPrefix;
     }
     var mirrorOrNull = _tryUpgradePrefix(_targetMirrorOrPrefix);
@@ -1135,7 +1123,7 @@
   }
 
   Future<LibraryMirror> loadLibrary() {
-    if (_targetMirrorOrPrefix is _LocalLibraryMirror) {
+    if (_targetMirrorOrPrefix is _LibraryMirror) {
       return new Future.value(_targetMirrorOrPrefix);
     }
     var savedPrefix = _targetMirrorOrPrefix;
@@ -1150,25 +1138,24 @@
   SourceLocation get location => null;
 }
 
-class _LocalCombinatorMirror extends _LocalMirror implements CombinatorMirror {
+class _CombinatorMirror extends Mirror implements CombinatorMirror {
   final List<Symbol> identifiers;
   final bool isShow;
 
-  _LocalCombinatorMirror._(identifierString, this.isShow)
+  _CombinatorMirror._(identifierString, this.isShow)
       : this.identifiers =
             new UnmodifiableListView<Symbol>(<Symbol>[_s(identifierString)]);
 
   bool get isHide => !isShow;
 }
 
-class _LocalMethodMirror extends _LocalDeclarationMirror
-    implements MethodMirror {
+class _MethodMirror extends _DeclarationMirror implements MethodMirror {
   final Type _instantiator;
   final bool isStatic;
   final int _kindFlags;
 
-  _LocalMethodMirror._(reflectee, String simpleName, this._owner,
-      this._instantiator, this.isStatic, this._kindFlags)
+  _MethodMirror._(reflectee, String simpleName, this._owner, this._instantiator,
+      this.isStatic, this._kindFlags)
       : super._(reflectee, _s(simpleName));
 
   static const kAbstract = 0;
@@ -1289,14 +1276,13 @@
   static String _MethodMirror_source(reflectee) native "MethodMirror_source";
 }
 
-class _LocalVariableMirror extends _LocalDeclarationMirror
-    implements VariableMirror {
+class _VariableMirror extends _DeclarationMirror implements VariableMirror {
   final DeclarationMirror owner;
   final bool isStatic;
   final bool isFinal;
   final bool isConst;
 
-  _LocalVariableMirror._(reflectee, String simpleName, this.owner, this._type,
+  _VariableMirror._(reflectee, String simpleName, this.owner, this._type,
       this.isStatic, this.isFinal, this.isConst)
       : super._(reflectee, _s(simpleName));
 
@@ -1304,11 +1290,11 @@
 
   Type get _instantiator {
     final o = owner; // Note: need local variable for promotion to happen.
-    if (o is _LocalClassMirror) {
+    if (o is _ClassMirror) {
       return o._instantiator;
-    } else if (o is _LocalMethodMirror) {
+    } else if (o is _MethodMirror) {
       return o._instantiator;
-    } else if (o is _LocalLibraryMirror) {
+    } else if (o is _LibraryMirror) {
       return o._instantiator;
     } else {
       throw new UnsupportedError("unexpected owner ${owner}");
@@ -1330,14 +1316,13 @@
       native "VariableMirror_type";
 }
 
-class _LocalParameterMirror extends _LocalVariableMirror
-    implements ParameterMirror {
+class _ParameterMirror extends _VariableMirror implements ParameterMirror {
   final int _position;
   final bool isOptional;
   final bool isNamed;
   final List _unmirroredMetadata;
 
-  _LocalParameterMirror._(
+  _ParameterMirror._(
       reflectee,
       String simpleName,
       DeclarationMirror owner,
@@ -1396,7 +1381,7 @@
       native "ParameterMirror_type";
 }
 
-class _SpecialTypeMirror extends _LocalMirror
+class _SpecialTypeMirror extends Mirror
     implements TypeMirror, DeclarationMirror {
   final Symbol simpleName;
 
@@ -1445,7 +1430,7 @@
 }
 
 class _Mirrors {
-  static MirrorSystem _currentMirrorSystem = new _LocalMirrorSystem();
+  static MirrorSystem _currentMirrorSystem = new _MirrorSystem();
   static MirrorSystem currentMirrorSystem() {
     return _currentMirrorSystem;
   }
@@ -1453,8 +1438,8 @@
   // Creates a new local mirror for some Object.
   static InstanceMirror reflect(Object reflectee) {
     return reflectee is Function
-        ? new _LocalClosureMirror._(reflectee)
-        : new _LocalInstanceMirror._(reflectee);
+        ? new _ClosureMirror._(reflectee)
+        : new _InstanceMirror._(reflectee);
   }
 
   static ClassMirror _makeLocalClassMirror(Type key)
@@ -1464,8 +1449,7 @@
   static Type _instantiateGenericType(Type key, typeArguments)
       native "Mirrors_instantiateGenericType";
 
-  static Expando<_LocalClassMirror> _declarationCache =
-      new Expando("ClassMirror");
+  static Expando<_ClassMirror> _declarationCache = new Expando("ClassMirror");
   static Expando<TypeMirror> _instantiationCache = new Expando("TypeMirror");
 
   static ClassMirror reflectClass(Type key) {
@@ -1488,7 +1472,7 @@
     if (typeMirror == null) {
       typeMirror = _makeLocalTypeMirror(key);
       _instantiationCache[key] = typeMirror;
-      if (typeMirror is _LocalClassMirror && !typeMirror._isGeneric) {
+      if (typeMirror is _ClassMirror && !typeMirror._isGeneric) {
         _declarationCache[key] = typeMirror;
       }
     }
diff --git a/runtime/lib/mirrors_patch.dart b/sdk/lib/_internal/vm/lib/mirrors_patch.dart
similarity index 94%
copy from runtime/lib/mirrors_patch.dart
copy to sdk/lib/_internal/vm/lib/mirrors_patch.dart
index 623fd65..9850e91 100644
--- a/runtime/lib/mirrors_patch.dart
+++ b/sdk/lib/_internal/vm/lib/mirrors_patch.dart
@@ -78,12 +78,12 @@
 
   @patch
   static Symbol getSymbol(String name, [LibraryMirror library]) {
-    if ((library != null && library is! _LocalLibraryMirror) ||
+    if ((library != null && library is! _LibraryMirror) ||
         ((name.length > 0) && (name[0] == '_') && (library == null))) {
       throw new ArgumentError(library);
     }
     if (library != null) {
-      name = _mangleName(name, (library as _LocalLibraryMirror)._reflectee);
+      name = _mangleName(name, (library as _LibraryMirror)._reflectee);
     }
     return new internal.Symbol.unvalidated(name);
   }
diff --git a/runtime/lib/null_patch.dart b/sdk/lib/_internal/vm/lib/null_patch.dart
similarity index 100%
rename from runtime/lib/null_patch.dart
rename to sdk/lib/_internal/vm/lib/null_patch.dart
diff --git a/runtime/lib/object_patch.dart b/sdk/lib/_internal/vm/lib/object_patch.dart
similarity index 100%
rename from runtime/lib/object_patch.dart
rename to sdk/lib/_internal/vm/lib/object_patch.dart
diff --git a/runtime/lib/print_patch.dart b/sdk/lib/_internal/vm/lib/print_patch.dart
similarity index 100%
rename from runtime/lib/print_patch.dart
rename to sdk/lib/_internal/vm/lib/print_patch.dart
diff --git a/runtime/lib/profiler.dart b/sdk/lib/_internal/vm/lib/profiler.dart
similarity index 100%
rename from runtime/lib/profiler.dart
rename to sdk/lib/_internal/vm/lib/profiler.dart
diff --git a/runtime/lib/regexp_patch.dart b/sdk/lib/_internal/vm/lib/regexp_patch.dart
similarity index 100%
rename from runtime/lib/regexp_patch.dart
rename to sdk/lib/_internal/vm/lib/regexp_patch.dart
diff --git a/runtime/lib/schedule_microtask_patch.dart b/sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart
similarity index 100%
rename from runtime/lib/schedule_microtask_patch.dart
rename to sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart
diff --git a/runtime/lib/stacktrace.dart b/sdk/lib/_internal/vm/lib/stacktrace.dart
similarity index 100%
rename from runtime/lib/stacktrace.dart
rename to sdk/lib/_internal/vm/lib/stacktrace.dart
diff --git a/runtime/lib/stopwatch_patch.dart b/sdk/lib/_internal/vm/lib/stopwatch_patch.dart
similarity index 100%
rename from runtime/lib/stopwatch_patch.dart
rename to sdk/lib/_internal/vm/lib/stopwatch_patch.dart
diff --git a/runtime/lib/string_buffer_patch.dart b/sdk/lib/_internal/vm/lib/string_buffer_patch.dart
similarity index 100%
rename from runtime/lib/string_buffer_patch.dart
rename to sdk/lib/_internal/vm/lib/string_buffer_patch.dart
diff --git a/runtime/lib/string_patch.dart b/sdk/lib/_internal/vm/lib/string_patch.dart
similarity index 98%
copy from runtime/lib/string_patch.dart
copy to sdk/lib/_internal/vm/lib/string_patch.dart
index c08bd49..837599b 100644
--- a/runtime/lib/string_patch.dart
+++ b/sdk/lib/_internal/vm/lib/string_patch.dart
@@ -948,7 +948,9 @@
 
 @pragma("vm:entry-point")
 class _OneByteString extends _StringBase {
-  factory _OneByteString._uninstantiable() { throw "Unreachable"; }
+  factory _OneByteString._uninstantiable() {
+    throw "Unreachable";
+  }
 
   @pragma("vm:exact-result-type", "dart:core#_Smi")
   int get hashCode native "String_getHashCode";
@@ -1254,7 +1256,9 @@
 
 @pragma("vm:entry-point")
 class _TwoByteString extends _StringBase {
-  factory _TwoByteString._uninstantiable() { throw "Unreachable"; }
+  factory _TwoByteString._uninstantiable() {
+    throw "Unreachable";
+  }
 
   static String _allocateFromTwoByteList(List<int> list, int start, int end)
       native "TwoByteString_allocateFromTwoByteList";
@@ -1274,7 +1278,9 @@
 
 @pragma("vm:entry-point")
 class _ExternalOneByteString extends _StringBase {
-  factory _ExternalOneByteString._uninstantiable() { throw "Unreachable"; }
+  factory _ExternalOneByteString._uninstantiable() {
+    throw "Unreachable";
+  }
 
   bool _isWhitespace(int codeUnit) {
     return _StringBase._isOneByteWhitespace(codeUnit);
@@ -1290,7 +1296,9 @@
 
 @pragma("vm:entry-point")
 class _ExternalTwoByteString extends _StringBase {
-  factory _ExternalTwoByteString._uninstantiable() { throw "Unreachable"; }
+  factory _ExternalTwoByteString._uninstantiable() {
+    throw "Unreachable";
+  }
 
   bool _isWhitespace(int codeUnit) {
     return _StringBase._isTwoByteWhitespace(codeUnit);
diff --git a/runtime/lib/symbol_patch.dart b/sdk/lib/_internal/vm/lib/symbol_patch.dart
similarity index 100%
rename from runtime/lib/symbol_patch.dart
rename to sdk/lib/_internal/vm/lib/symbol_patch.dart
diff --git a/runtime/lib/timeline.dart b/sdk/lib/_internal/vm/lib/timeline.dart
similarity index 100%
rename from runtime/lib/timeline.dart
rename to sdk/lib/_internal/vm/lib/timeline.dart
diff --git a/runtime/lib/timer_impl.dart b/sdk/lib/_internal/vm/lib/timer_impl.dart
similarity index 100%
rename from runtime/lib/timer_impl.dart
rename to sdk/lib/_internal/vm/lib/timer_impl.dart
diff --git a/runtime/lib/timer_patch.dart b/sdk/lib/_internal/vm/lib/timer_patch.dart
similarity index 100%
rename from runtime/lib/timer_patch.dart
rename to sdk/lib/_internal/vm/lib/timer_patch.dart
diff --git a/runtime/lib/type_patch.dart b/sdk/lib/_internal/vm/lib/type_patch.dart
similarity index 100%
rename from runtime/lib/type_patch.dart
rename to sdk/lib/_internal/vm/lib/type_patch.dart
diff --git a/runtime/lib/typed_data_patch.dart b/sdk/lib/_internal/vm/lib/typed_data_patch.dart
similarity index 100%
rename from runtime/lib/typed_data_patch.dart
rename to sdk/lib/_internal/vm/lib/typed_data_patch.dart
diff --git a/runtime/lib/uri_patch.dart b/sdk/lib/_internal/vm/lib/uri_patch.dart
similarity index 100%
rename from runtime/lib/uri_patch.dart
rename to sdk/lib/_internal/vm/lib/uri_patch.dart
diff --git a/sdk/lib/_internal/vm/lib/wasm_patch.dart b/sdk/lib/_internal/vm/lib/wasm_patch.dart
new file mode 100644
index 0000000..f0c2794
--- /dev/null
+++ b/sdk/lib/_internal/vm/lib/wasm_patch.dart
@@ -0,0 +1,149 @@
+// 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:_internal' show patch;
+import "dart:nativewrappers" show NativeFieldWrapperClass1;
+import 'dart:typed_data';
+
+@patch
+@pragma("vm:entry-point")
+class Int32 {}
+
+@patch
+@pragma("vm:entry-point")
+class Int64 {}
+
+@patch
+@pragma("vm:entry-point")
+class Float {}
+
+@patch
+@pragma("vm:entry-point")
+class Double {}
+
+@patch
+@pragma("vm:entry-point")
+class Void {}
+
+@patch
+class WasmModule {
+  @patch
+  factory WasmModule(Uint8List data) {
+    return _NativeWasmModule(data);
+  }
+}
+
+@patch
+class WasmMemory {
+  @patch
+  factory WasmMemory(int initialPages, [int maxPages]) {
+    return _NativeWasmMemory(initialPages, maxPages);
+  }
+}
+
+@patch
+class WasmImports {
+  @patch
+  factory WasmImports(String moduleName) {
+    return _NativeWasmImports(moduleName);
+  }
+}
+
+class _NativeWasmModule extends NativeFieldWrapperClass1 implements WasmModule {
+  _NativeWasmModule(Uint8List data) {
+    _init(data);
+  }
+
+  WasmInstance instantiate(covariant _NativeWasmImports imports) {
+    return _NativeWasmInstance(this, imports);
+  }
+
+  void _init(Uint8List data) native 'Wasm_initModule';
+}
+
+class _NativeWasmImports extends NativeFieldWrapperClass1
+    implements WasmImports {
+  List<WasmMemory> _memories;
+
+  _NativeWasmImports(String moduleName) : _memories = [] {
+    _init(moduleName);
+  }
+
+  void addMemory(String name, WasmMemory memory) {
+    _memories.add(memory);
+    _addMemory(name, memory);
+  }
+
+  void addGlobal<T>(String name, num value, bool mutable) {
+    _addGlobal(name, value, T, mutable);
+  }
+
+  void _init(String moduleName) native 'Wasm_initImports';
+  void _addMemory(String name, WasmMemory memory) native 'Wasm_addMemoryImport';
+  void _addGlobal(String name, num value, Type type, bool mutable)
+      native 'Wasm_addGlobalImport';
+}
+
+class _NativeWasmMemory extends NativeFieldWrapperClass1 implements WasmMemory {
+  int _pages;
+  Uint8List _buffer;
+
+  _NativeWasmMemory(int initialPages, int maxPages) : _pages = initialPages {
+    _buffer = _init(initialPages, maxPages);
+  }
+
+  int get lengthInPages => _pages;
+  int get lengthInBytes => _buffer.lengthInBytes;
+  int operator [](int index) => _buffer[index];
+  void operator []=(int index, int value) {
+    _buffer[index] = value;
+  }
+
+  int grow(int deltaPages) {
+    int oldPages = _pages;
+    _buffer = _grow(deltaPages);
+    _pages += deltaPages;
+    return oldPages;
+  }
+
+  Uint8List _init(int initialPages, int maxPages) native 'Wasm_initMemory';
+  Uint8List _grow(int deltaPages) native 'Wasm_growMemory';
+}
+
+class _NativeWasmInstance extends NativeFieldWrapperClass1
+    implements WasmInstance {
+  _NativeWasmModule _module;
+  _NativeWasmImports _imports;
+
+  _NativeWasmInstance(_NativeWasmModule module, _NativeWasmImports imports)
+      : _module = module,
+        _imports = imports {
+    _init(module, imports);
+  }
+
+  WasmFunction<T> lookupFunction<T extends Function>(String name) {
+    return _NativeWasmFunction<T>(this, name);
+  }
+
+  void _init(_NativeWasmModule module, _NativeWasmImports imports)
+      native 'Wasm_initInstance';
+}
+
+class _NativeWasmFunction<T extends Function> extends NativeFieldWrapperClass1
+    implements WasmFunction<T> {
+  _NativeWasmInstance _inst;
+
+  _NativeWasmFunction(_NativeWasmInstance inst, String name) : _inst = inst {
+    _init(inst, name, T);
+  }
+
+  num call(List<num> args) {
+    var arg_copy = List<num>.from(args, growable: false);
+    return _call(arg_copy);
+  }
+
+  void _init(_NativeWasmInstance inst, String name, Type fnType)
+      native 'Wasm_initFunction';
+  num _call(List<num> args) native 'Wasm_callFunction';
+}
diff --git a/runtime/lib/weak_property.dart b/sdk/lib/_internal/vm/lib/weak_property.dart
similarity index 100%
rename from runtime/lib/weak_property.dart
rename to sdk/lib/_internal/vm/lib/weak_property.dart
diff --git a/sdk/lib/html/html_common/conversions.dart b/sdk/lib/html/html_common/conversions.dart
index 4c31efb..5fa8385 100644
--- a/sdk/lib/html/html_common/conversions.dart
+++ b/sdk/lib/html/html_common/conversions.dart
@@ -76,6 +76,9 @@
 
   cleanupSlots() {} // Will be needed if we mark objects with a property.
   bool cloneNotRequired(object);
+  JSObject newJsObject();
+  void forEachObjectKey(object, action(key, value));
+  void putIntoObject(object, key, value);
   newJsMap();
   List newJsList(length);
   void putIntoMap(map, key, value);
@@ -134,6 +137,19 @@
       return copy;
     }
 
+    if (e is JSObject) {
+      var slot = findSlot(e);
+      var copy = readSlot(slot);
+      if (copy != null) return copy;
+      copy = newJsObject();
+      writeSlot(slot, copy);
+      // TODO: Consider inlining this so we don't allocate a closure.
+      forEachObjectKey(e, (key, value) {
+        putIntoObject(copy, key, walk(value));
+      });
+      return copy;
+    }
+
     throw new UnimplementedError('structured clone of other type');
   }
 
diff --git a/sdk/lib/html/html_common/conversions_dart2js.dart b/sdk/lib/html/html_common/conversions_dart2js.dart
index 36153cf..d077775 100644
--- a/sdk/lib/html/html_common/conversions_dart2js.dart
+++ b/sdk/lib/html/html_common/conversions_dart2js.dart
@@ -53,6 +53,18 @@
         .convertNativeToDart_AcceptStructuredClone(object, mustCopy: mustCopy);
 
 class _StructuredCloneDart2Js extends _StructuredClone {
+  JSObject newJsObject() => JS('JSObject', '{}');
+
+  void forEachObjectKey(object, action(key, value)) {
+    for (final key
+        in JS('returns:JSExtendableArray;new:true', 'Object.keys(#)', object)) {
+      action(key, JS('var', '#[#]', object, key));
+    }
+  }
+
+  void putIntoObject(object, key, value) =>
+      JS('void', '#[#] = #', object, key, value);
+
   newJsMap() => JS('var', '{}');
   putIntoMap(map, key, value) => JS('void', '#[#] = #', map, key, value);
   newJsList(length) => JS('JSExtendableArray', 'new Array(#)', length);
diff --git a/sdk/lib/html/html_common/html_common_dart2js.dart b/sdk/lib/html/html_common/html_common_dart2js.dart
index f162ad8..de8d89e 100644
--- a/sdk/lib/html/html_common/html_common_dart2js.dart
+++ b/sdk/lib/html/html_common/html_common_dart2js.dart
@@ -13,7 +13,7 @@
 import 'dart:_native_typed_data';
 import 'dart:_js_helper' show Creates, Returns, convertDartClosureToJS;
 import 'dart:_foreign_helper' show JS;
-import 'dart:_interceptors' show Interceptor, JSExtendableArray;
+import 'dart:_interceptors' show Interceptor, JSExtendableArray, JSObject;
 
 import 'dart:_metadata';
 export 'dart:_metadata';
diff --git a/sdk/lib/js/dart2js/js_dart2js.dart b/sdk/lib/js/dart2js/js_dart2js.dart
index 535227b..23656d7 100644
--- a/sdk/lib/js/dart2js/js_dart2js.dart
+++ b/sdk/lib/js/dart2js/js_dart2js.dart
@@ -2,85 +2,86 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/**
- * Support for interoperating with JavaScript.
- *
- * This library provides access to JavaScript objects from Dart, allowing
- * Dart code to get and set properties, and call methods of JavaScript objects
- * and invoke JavaScript functions. The library takes care of converting
- * between Dart and JavaScript objects where possible, or providing proxies if
- * conversion isn't possible.
- *
- * This library does not yet make Dart objects usable from JavaScript, their
- * methods and proeprties are not accessible, though it does allow Dart
- * functions to be passed into and called from JavaScript.
- *
- * [JsObject] is the core type and represents a proxy of a JavaScript object.
- * JsObject gives access to the underlying JavaScript objects properties and
- * methods. `JsObject`s can be acquired by calls to JavaScript, or they can be
- * created from proxies to JavaScript constructors.
- *
- * The top-level getter [context] provides a [JsObject] that represents the
- * global object in JavaScript, usually `window`.
- *
- * The following example shows an alert dialog via a JavaScript call to the
- * global function `alert()`:
- *
- *     import 'dart:js';
- *
- *     main() => context.callMethod('alert', ['Hello from Dart!']);
- *
- * This example shows how to create a [JsObject] from a JavaScript constructor
- * and access its properties:
- *
- *     import 'dart:js';
- *
- *     main() {
- *       var object = new JsObject(context['Object']);
- *       object['greeting'] = 'Hello';
- *       object['greet'] = (name) => "${object['greeting']} $name";
- *       var message = object.callMethod('greet', ['JavaScript']);
- *       context['console'].callMethod('log', [message]);
- *     }
- *
- * ## Proxying and automatic conversion
- *
- * When setting properties on a JsObject or passing arguments to a Javascript
- * method or function, Dart objects are automatically converted or proxied to
- * JavaScript objects. When accessing JavaScript properties, or when a Dart
- * closure is invoked from JavaScript, the JavaScript objects are also
- * converted to Dart.
- *
- * Functions and closures are proxied in such a way that they are callable. A
- * Dart closure assigned to a JavaScript property is proxied by a function in
- * JavaScript. A JavaScript function accessed from Dart is proxied by a
- * [JsFunction], which has a [apply] method to invoke it.
- *
- * The following types are transferred directly and not proxied:
- *
- *   * Basic types: `null`, `bool`, `num`, `String`, `DateTime`
- *   * `TypedData`, including its subclasses like `Int32List`, but _not_
- *     `ByteBuffer`
- *   * When compiling for the web, also: `Blob`, `Event`, `ImageData`,
- *     `KeyRange`, `Node`, and `Window`.
- *
- * ## Converting collections with JsObject.jsify()
- *
- * To create a JavaScript collection from a Dart collection use the
- * [JsObject.jsify] constructor, which converts Dart [Map]s and [Iterable]s
- * into JavaScript Objects and Arrays.
- *
- * The following expression creates a new JavaScript object with the properties
- * `a` and `b` defined:
- *
- *     var jsMap = new JsObject.jsify({'a': 1, 'b': 2});
- *
- * This expression creates a JavaScript array:
- *
- *     var jsArray = new JsObject.jsify([1, 2, 3]);
- *
- * {@category Web}
- */
+/// Low-level support for interoperating with JavaScript.
+///
+/// You should usually use `package:js` instead of this library. For more
+/// information, see the [JS interop page](https://dart.dev/web/js-interop).
+///
+/// This library provides access to JavaScript objects from Dart, allowing
+/// Dart code to get and set properties, and call methods of JavaScript objects
+/// and invoke JavaScript functions. The library takes care of converting
+/// between Dart and JavaScript objects where possible, or providing proxies if
+/// conversion isn't possible.
+///
+/// This library does not make Dart objects usable from JavaScript, their
+/// methods and properties are not accessible, though it does allow Dart
+/// functions to be passed into and called from JavaScript.
+///
+/// [JsObject] is the core type and represents a proxy of a JavaScript object.
+/// JsObject gives access to the underlying JavaScript objects properties and
+/// methods. `JsObject`s can be acquired by calls to JavaScript, or they can be
+/// created from proxies to JavaScript constructors.
+///
+/// The top-level getter [context] provides a [JsObject] that represents the
+/// global object in JavaScript, usually `window`.
+///
+/// The following example shows an alert dialog via a JavaScript call to the
+/// global function `alert()`:
+///
+///     import 'dart:js';
+///
+///     main() => context.callMethod('alert', ['Hello from Dart!']);
+///
+/// This example shows how to create a [JsObject] from a JavaScript constructor
+/// and access its properties:
+///
+///     import 'dart:js';
+///
+///     main() {
+///       var object = JsObject(context['Object']);
+///       object['greeting'] = 'Hello';
+///       object['greet'] = (name) => "${object['greeting']} $name";
+///       var message = object.callMethod('greet', ['JavaScript']);
+///       context['console'].callMethod('log', [message]);
+///     }
+///
+/// ## Proxying and automatic conversion
+///
+/// When setting properties on a JsObject or passing arguments to a Javascript
+/// method or function, Dart objects are automatically converted or proxied to
+/// JavaScript objects. When accessing JavaScript properties, or when a Dart
+/// closure is invoked from JavaScript, the JavaScript objects are also
+/// converted to Dart.
+///
+/// Functions and closures are proxied in such a way that they are callable. A
+/// Dart closure assigned to a JavaScript property is proxied by a function in
+/// JavaScript. A JavaScript function accessed from Dart is proxied by a
+/// [JsFunction], which has a [apply] method to invoke it.
+///
+/// The following types are transferred directly and not proxied:
+///
+///   * Basic types: `null`, `bool`, `num`, `String`, `DateTime`
+///   * `TypedData`, including its subclasses like `Int32List`, but _not_
+///     `ByteBuffer`
+///   * When compiling for the web, also: `Blob`, `Event`, `ImageData`,
+///     `KeyRange`, `Node`, and `Window`.
+///
+/// ## Converting collections with JsObject.jsify()
+///
+/// To create a JavaScript collection from a Dart collection use the
+/// [JsObject.jsify] constructor, which converts Dart [Map]s and [Iterable]s
+/// into JavaScript Objects and Arrays.
+///
+/// The following expression creates a new JavaScript object with the properties
+/// `a` and `b` defined:
+///
+///     var jsMap = JsObject.jsify({'a': 1, 'b': 2});
+///
+/// This expression creates a JavaScript array:
+///
+///     var jsArray = JsObject.jsify([1, 2, 3]);
+///
+/// {@category Web}
 library dart.js;
 
 import 'dart:collection' show HashMap, ListMixin;
@@ -99,6 +100,7 @@
 
 export 'dart:_interceptors' show JavaScriptObject;
 
+/// The JavaScript global object, usually `window`.
 final JsObject context = _wrapToDart(JS('', 'self'));
 
 _convertDartFunction(Function f, {bool captureThis: false}) {
@@ -121,56 +123,51 @@
   if (captureThis) {
     arguments = [self]..addAll(arguments);
   }
-  var dartArgs = new List.from(arguments.map(_convertToDart));
+  var dartArgs = List.from(arguments.map(_convertToDart));
   return _convertToJS(Function.apply(callback, dartArgs));
 }
 
-/**
- * Proxies a JavaScript object to Dart.
- *
- * The properties of the JavaScript object are accessible via the `[]` and
- * `[]=` operators. Methods are callable via [callMethod].
- */
+/// A proxy on a JavaScript object.
+///
+/// The properties of the JavaScript object are accessible via the `[]` and
+/// `[]=` operators. Methods are callable via [callMethod].
 class JsObject {
   // The wrapped JS object.
   final dynamic _jsObject;
 
-  // This shoud only be called from _wrapToDart
+  // This should only be called from _wrapToDart
   JsObject._fromJs(this._jsObject) {
     assert(_jsObject != null);
   }
 
-  /**
-   * Constructs a new JavaScript object from [constructor] and returns a proxy
-   * to it.
-   */
+  /// Constructs a JavaScript object from its native [constructor] and returns
+  /// a proxy to it.
   factory JsObject(JsFunction constructor, [List arguments]) {
-    var constr = _convertToJS(constructor);
+    var ctor = _convertToJS(constructor);
     if (arguments == null) {
-      return _wrapToDart(JS('', 'new #()', constr));
+      return _wrapToDart(JS('', 'new #()', ctor));
     }
 
     if (JS('bool', '# instanceof Array', arguments)) {
       int argumentCount = JS('int', '#.length', arguments);
       switch (argumentCount) {
         case 0:
-          return _wrapToDart(JS('', 'new #()', constr));
+          return _wrapToDart(JS('', 'new #()', ctor));
 
         case 1:
           var arg0 = _convertToJS(JS('', '#[0]', arguments));
-          return _wrapToDart(JS('', 'new #(#)', constr, arg0));
+          return _wrapToDart(JS('', 'new #(#)', ctor, arg0));
 
         case 2:
           var arg0 = _convertToJS(JS('', '#[0]', arguments));
           var arg1 = _convertToJS(JS('', '#[1]', arguments));
-          return _wrapToDart(JS('', 'new #(#, #)', constr, arg0, arg1));
+          return _wrapToDart(JS('', 'new #(#, #)', ctor, arg0, arg1));
 
         case 3:
           var arg0 = _convertToJS(JS('', '#[0]', arguments));
           var arg1 = _convertToJS(JS('', '#[1]', arguments));
           var arg2 = _convertToJS(JS('', '#[2]', arguments));
-          return _wrapToDart(
-              JS('', 'new #(#, #, #)', constr, arg0, arg1, arg2));
+          return _wrapToDart(JS('', 'new #(#, #, #)', ctor, arg0, arg1, arg2));
 
         case 4:
           var arg0 = _convertToJS(JS('', '#[0]', arguments));
@@ -178,7 +175,7 @@
           var arg2 = _convertToJS(JS('', '#[2]', arguments));
           var arg3 = _convertToJS(JS('', '#[3]', arguments));
           return _wrapToDart(
-              JS('', 'new #(#, #, #, #)', constr, arg0, arg1, arg2, arg3));
+              JS('', 'new #(#, #, #, #)', ctor, arg0, arg1, arg2, arg3));
       }
     }
 
@@ -190,7 +187,7 @@
     // After that, use the JavaScript 'new' operator which overrides any binding
     // of 'this' with the new instance.
     var args = <dynamic>[null]..addAll(arguments.map(_convertToJS));
-    var factoryFunction = JS('', '#.bind.apply(#, #)', constr, constr, args);
+    var factoryFunction = JS('', '#.bind.apply(#, #)', ctor, ctor, args);
     // Without this line, calling factoryFunction as a constructor throws
     JS('String', 'String(#)', factoryFunction);
     // This could return an UnknownJavaScriptObject, or a native
@@ -201,48 +198,44 @@
 
     // TODO(sra): Investigate:
     //
-    //     var jsObj = JS('', 'Object.create(#.prototype)', constr);
-    //     JS('', '#.apply(#, #)', constr, jsObj,
+    //     var jsObj = JS('', 'Object.create(#.prototype)', ctor);
+    //     JS('', '#.apply(#, #)', ctor, jsObj,
     //         []..addAll(arguments.map(_convertToJS)));
     //     return _wrapToDart(jsObj);
   }
 
-  /**
-   * Constructs a [JsObject] that proxies a native Dart object; _for expert use
-   * only_.
-   *
-   * Use this constructor only if you wish to get access to JavaScript
-   * properties attached to a browser host object, such as a Node or Blob, that
-   * is normally automatically converted into a native Dart object.
-   *
-   * An exception will be thrown if [object] either is `null` or has the type
-   * `bool`, `num`, or `String`.
-   */
+  /// Constructs a [JsObject] that proxies a native Dart object; _for expert use
+  /// only_.
+  ///
+  /// Use this constructor only if you wish to get access to JavaScript
+  /// properties attached to a browser host object, such as a Node or Blob, that
+  /// is normally automatically converted into a native Dart object.
+  ///
+  /// An exception will be thrown if [object] either is `null` or has the type
+  /// `bool`, `num`, or `String`.
   factory JsObject.fromBrowserObject(object) {
     if (object is num || object is String || object is bool || object == null) {
-      throw new ArgumentError("object cannot be a num, string, bool, or null");
+      throw ArgumentError("object cannot be a num, string, bool, or null");
     }
     return _wrapToDart(_convertToJS(object));
   }
 
-  /**
-   * Recursively converts a JSON-like collection of Dart objects to a
-   * collection of JavaScript objects and returns a [JsObject] proxy to it.
-   *
-   * [object] must be a [Map] or [Iterable], the contents of which are also
-   * converted. Maps and Iterables are copied to a new JavaScript object.
-   * Primitives and other transferrable values are directly converted to their
-   * JavaScript type, and all other objects are proxied.
-   */
+  /// Recursively converts a JSON-like collection of Dart objects to a
+  /// collection of JavaScript objects and returns a [JsObject] proxy to it.
+  ///
+  /// [object] must be a [Map] or [Iterable], the contents of which are also
+  /// converted. Maps and Iterables are copied to a new JavaScript object.
+  /// Primitives and other transferable values are directly converted to their
+  /// JavaScript type, and all other objects are proxied.
   factory JsObject.jsify(object) {
     if ((object is! Map) && (object is! Iterable)) {
-      throw new ArgumentError("object must be a Map or Iterable");
+      throw ArgumentError("object must be a Map or Iterable");
     }
     return _wrapToDart(_convertDataTree(object));
   }
 
   static _convertDataTree(data) {
-    var _convertedObjects = new HashMap.identity();
+    var _convertedObjects = HashMap.identity();
 
     _convert(o) {
       if (_convertedObjects.containsKey(o)) {
@@ -252,7 +245,7 @@
         final convertedMap = JS('=Object', '{}');
         _convertedObjects[o] = convertedMap;
         for (var key in o.keys) {
-          JS('=Object', '#[#]=#', convertedMap, key, _convert(o[key]));
+          JS('=Object', '#[#] = #', convertedMap, key, _convert(o[key]));
         }
         return convertedMap;
       } else if (o is Iterable) {
@@ -268,30 +261,26 @@
     return _convert(data);
   }
 
-  /**
-   * Returns the value associated with [property] from the proxied JavaScript
-   * object.
-   *
-   * The type of [property] must be either [String] or [num].
-   */
+  /// Returns the value associated with [property] from the proxied JavaScript
+  /// object.
+  ///
+  /// The type of [property] must be either [String] or [num].
   dynamic operator [](property) {
     if (property is! String && property is! num) {
-      throw new ArgumentError("property is not a String or num");
+      throw ArgumentError("property is not a String or num");
     }
     return _convertToDart(JS('', '#[#]', _jsObject, property));
   }
 
-  /**
-   * Sets the value associated with [property] on the proxied JavaScript
-   * object.
-   *
-   * The type of [property] must be either [String] or [num].
-   */
-  operator []=(property, value) {
+  // Sets the value associated with [property] on the proxied JavaScript
+  // object.
+  //
+  // The type of [property] must be either [String] or [num].
+  void operator []=(property, value) {
     if (property is! String && property is! num) {
-      throw new ArgumentError("property is not a String or num");
+      throw ArgumentError("property is not a String or num");
     }
-    JS('', '#[#]=#', _jsObject, property, _convertToJS(value));
+    JS('', '#[#] = #', _jsObject, property, _convertToJS(value));
   }
 
   int get hashCode => 0;
@@ -299,43 +288,35 @@
   bool operator ==(other) =>
       other is JsObject && JS('bool', '# === #', _jsObject, other._jsObject);
 
-  /**
-   * Returns `true` if the JavaScript object contains the specified property
-   * either directly or though its prototype chain.
-   *
-   * This is the equivalent of the `in` operator in JavaScript.
-   */
+  /// Returns `true` if the JavaScript object contains the specified property
+  /// either directly or though its prototype chain.
+  ///
+  /// This is the equivalent of the `in` operator in JavaScript.
   bool hasProperty(property) {
     if (property is! String && property is! num) {
-      throw new ArgumentError("property is not a String or num");
+      throw ArgumentError("property is not a String or num");
     }
     return JS('bool', '# in #', property, _jsObject);
   }
 
-  /**
-   * Removes [property] from the JavaScript object.
-   *
-   * This is the equivalent of the `delete` operator in JavaScript.
-   */
+  /// Removes [property] from the JavaScript object.
+  ///
+  /// This is the equivalent of the `delete` operator in JavaScript.
   void deleteProperty(property) {
     if (property is! String && property is! num) {
-      throw new ArgumentError("property is not a String or num");
+      throw ArgumentError("property is not a String or num");
     }
     JS('bool', 'delete #[#]', _jsObject, property);
   }
 
-  /**
-   * Returns `true` if the JavaScript object has [type] in its prototype chain.
-   *
-   * This is the equivalent of the `instanceof` operator in JavaScript.
-   */
+  /// Returns `true` if the JavaScript object has [type] in its prototype chain.
+  ///
+  /// This is the equivalent of the `instanceof` operator in JavaScript.
   bool instanceof(JsFunction type) {
     return JS('bool', '# instanceof #', _jsObject, _convertToJS(type));
   }
 
-  /**
-   * Returns the result of the JavaScript objects `toString` method.
-   */
+  /// Returns the result of the JavaScript objects `toString` method.
   String toString() {
     try {
       return JS('String', 'String(#)', _jsObject);
@@ -344,66 +325,47 @@
     }
   }
 
-  /**
-   * Calls [method] on the JavaScript object with the arguments [args] and
-   * returns the result.
-   *
-   * The type of [method] must be either [String] or [num].
-   */
+  /// Calls [method] on the JavaScript object with the arguments [args] and
+  /// returns the result.
+  ///
+  /// The type of [method] must be either [String] or [num].
   dynamic callMethod(method, [List args]) {
     if (method is! String && method is! num) {
-      throw new ArgumentError("method is not a String or num");
+      throw ArgumentError("method is not a String or num");
     }
-    return _convertToDart(JS(
-        '',
-        '#[#].apply(#, #)',
-        _jsObject,
-        method,
-        _jsObject,
-        args == null ? null : new List.from(args.map(_convertToJS))));
+    return _convertToDart(JS('', '#[#].apply(#, #)', _jsObject, method,
+        _jsObject, args == null ? null : List.from(args.map(_convertToJS))));
   }
 }
 
-/**
- * Proxies a JavaScript Function object.
- */
+/// A proxy on a JavaScript Function object.
 class JsFunction extends JsObject {
-  /**
-   * Returns a [JsFunction] that captures its 'this' binding and calls [f]
-   * with the value of this passed as the first argument.
-   */
+  /// Returns a [JsFunction] that captures its 'this' binding and calls [f]
+  /// with the value of JavaScript `this` passed as the first argument.
   factory JsFunction.withThis(Function f) {
     var jsFunc = _convertDartFunction(f, captureThis: true);
-    return new JsFunction._fromJs(jsFunc);
+    return JsFunction._fromJs(jsFunc);
   }
 
   JsFunction._fromJs(jsObject) : super._fromJs(jsObject);
 
-  /**
-   * Invokes the JavaScript function with arguments [args]. If [thisArg] is
-   * supplied it is the value of `this` for the invocation.
-   */
+  /// Invokes the JavaScript function with arguments [args]. If [thisArg] is
+  /// supplied it is the value of `this` for the invocation.
   dynamic apply(List args, {thisArg}) => _convertToDart(JS(
       '',
       '#.apply(#, #)',
       _jsObject,
       _convertToJS(thisArg),
-      args == null ? null : new List.from(args.map(_convertToJS))));
+      args == null ? null : List.from(args.map(_convertToJS))));
 }
 
-/**
- * A [List] that proxies a JavaScript array.
- */
+/// A [List] that proxies a JavaScript array.
 class JsArray<E> extends JsObject with ListMixin<E> {
-  /**
-   * Creates a new JavaScript array.
-   */
+  /// Creates an empty JavaScript array.
   JsArray() : super._fromJs([]);
 
-  /**
-   * Creates a new JavaScript array and initializes it to the contents of
-   * [other].
-   */
+  /// Creates a new JavaScript array and initializes it to the contents of
+  /// [other].
   JsArray.from(Iterable<E> other)
       : super._fromJs([]..addAll(other.map(_convertToJS)));
 
@@ -411,22 +373,22 @@
 
   _checkIndex(int index) {
     if (index is int && (index < 0 || index >= length)) {
-      throw new RangeError.range(index, 0, length);
+      throw RangeError.range(index, 0, length);
     }
   }
 
   _checkInsertIndex(int index) {
     if (index is int && (index < 0 || index >= length + 1)) {
-      throw new RangeError.range(index, 0, length);
+      throw RangeError.range(index, 0, length);
     }
   }
 
   static _checkRange(int start, int end, int length) {
     if (start < 0 || start > length) {
-      throw new RangeError.range(start, 0, length);
+      throw RangeError.range(start, 0, length);
     }
     if (end < start || end > length) {
-      throw new RangeError.range(end, start, length);
+      throw RangeError.range(end, start, length);
     }
   }
 
@@ -457,7 +419,7 @@
     if (JS('bool', 'typeof # === "number" && (# >>> 0) === #', len, len, len)) {
       return JS('int', '#', len);
     }
-    throw new StateError('Bad JsArray length');
+    throw StateError('Bad JsArray length');
   }
 
   void set length(int length) {
@@ -473,7 +435,7 @@
   void addAll(Iterable<E> iterable) {
     var list = (JS('bool', '# instanceof Array', iterable))
         ? iterable
-        : new List.from(iterable);
+        : List.from(iterable);
     callMethod('push', list);
   }
 
@@ -488,7 +450,7 @@
   }
 
   E removeLast() {
-    if (length == 0) throw new RangeError(-1);
+    if (length == 0) throw RangeError(-1);
     return callMethod('pop');
   }
 
@@ -501,7 +463,7 @@
     _checkRange(start, end, this.length);
     int length = end - start;
     if (length == 0) return;
-    if (skipCount < 0) throw new ArgumentError(skipCount);
+    if (skipCount < 0) throw ArgumentError(skipCount);
     var args = <dynamic>[start, length]
       ..addAll(iterable.skip(skipCount).take(length));
     callMethod('splice', args);
@@ -612,7 +574,7 @@
     return JS('TypedData', '#', o);
   } else if (JS('bool', '# instanceof Date', o)) {
     var ms = JS('num', '#.getTime()', o);
-    return new DateTime.fromMillisecondsSinceEpoch(ms);
+    return DateTime.fromMillisecondsSinceEpoch(ms);
   } else if (JS('bool', '#.constructor === #', o, _dartProxyCtor)) {
     return JS('', '#.o', o);
   } else {
@@ -623,14 +585,14 @@
 Object _wrapToDart(o) {
   if (JS('bool', 'typeof # == "function"', o)) {
     return _getDartProxy(
-        o, DART_CLOSURE_PROPERTY_NAME, (o) => new JsFunction._fromJs(o));
+        o, DART_CLOSURE_PROPERTY_NAME, (o) => JsFunction._fromJs(o));
   }
   if (JS('bool', '# instanceof Array', o)) {
     return _getDartProxy(
-        o, _DART_OBJECT_PROPERTY_NAME, (o) => new JsArray._fromJs(o));
+        o, _DART_OBJECT_PROPERTY_NAME, (o) => JsArray._fromJs(o));
   }
   return _getDartProxy(
-      o, _DART_OBJECT_PROPERTY_NAME, (o) => new JsObject._fromJs(o));
+      o, _DART_OBJECT_PROPERTY_NAME, (o) => JsObject._fromJs(o));
 }
 
 Object _getDartProxy(o, String propertyName, createProxy(o)) {
@@ -649,9 +611,6 @@
   return dartProxy;
 }
 
-// ---------------------------------------------------------------------------
-// Start of methods for new style Dart-JS interop.
-
 _convertDartFunctionFast(Function f) {
   var existing = JS('', '#.#', f, _JS_FUNCTION_PROPERTY_NAME);
   if (existing != null) return existing;
@@ -698,6 +657,17 @@
   return Function.apply(callback, [self]..addAll(arguments));
 }
 
+/// Returns a wrapper around function [f] that can be called from JavaScript
+/// using `package:js` JavaScript interop.
+///
+/// The calling conventions in Dart2Js differ from JavaScript and so, by
+/// default, it is not possible to call a Dart function directly. Wrapping with
+/// `allowInterop` creates a function that can be called from JavaScript or
+/// Dart. The semantics of the wrapped function are still more strict than
+/// JavaScript, and the function will throw if called with too many or too few
+/// arguments.
+///
+/// Calling this method repeatedly on a function will return the same result.
 F allowInterop<F extends Function>(F f) {
   if (JS('bool', 'typeof(#) == "function"', f)) {
     // Already supports interop, just use the existing function.
@@ -707,10 +677,17 @@
   }
 }
 
+/// Returns a wrapper around function [f] that can be called from JavaScript
+/// using `package:js` JavaScript interop, passing JavaScript `this` as the first
+/// argument.
+///
+/// See [allowInterop].
+///
+/// When called from Dart, [null] will be passed as the first argument.
 Function allowInteropCaptureThis(Function f) {
   if (JS('bool', 'typeof(#) == "function"', f)) {
     // Behavior when the function is already a JS function is unspecified.
-    throw new ArgumentError(
+    throw ArgumentError(
         "Function is already a JS function so cannot capture this.");
     return f;
   } else {
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index 663991f..a6c8390 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -4,150 +4,150 @@
   "vm": {
     "libraries": {
       "_builtin": {
-        "uri": "../../runtime/bin/builtin.dart"
+        "uri": "_internal/vm/bin/builtin.dart"
       },
       "cli": {
         "patches": [
-          "../../runtime/bin/cli_patch.dart"
+          "_internal/vm/bin/cli_patch.dart"
         ],
         "uri": "cli/cli.dart"
       },
       "core": {
         "patches": [
-          "../../runtime/lib/core_patch.dart",
-          "../../runtime/lib/array.dart",
-          "../../runtime/lib/array_patch.dart",
-          "../../runtime/lib/bigint_patch.dart",
-          "../../runtime/lib/bool_patch.dart",
-          "../../runtime/lib/date_patch.dart",
-          "../../runtime/lib/double.dart",
-          "../../runtime/lib/double_patch.dart",
-          "../../runtime/lib/errors_patch.dart",
-          "../../runtime/lib/expando_patch.dart",
-          "../../runtime/lib/function.dart",
-          "../../runtime/lib/function_patch.dart",
-          "../../runtime/lib/growable_array.dart",
-          "../../runtime/lib/identical_patch.dart",
-          "../../runtime/lib/immutable_map.dart",
-          "../../runtime/lib/integers.dart",
-          "../../runtime/lib/integers_patch.dart",
-          "../../runtime/lib/invocation_mirror_patch.dart",
-          "../../runtime/lib/lib_prefix.dart",
-          "../../runtime/lib/map_patch.dart",
-          "../../runtime/lib/null_patch.dart",
-          "../../runtime/lib/object_patch.dart",
-          "../../runtime/lib/regexp_patch.dart",
-          "../../runtime/lib/stacktrace.dart",
-          "../../runtime/lib/stopwatch_patch.dart",
-          "../../runtime/lib/string_buffer_patch.dart",
-          "../../runtime/lib/string_patch.dart",
-          "../../runtime/lib/type_patch.dart",
-          "../../runtime/lib/uri_patch.dart",
-          "../../runtime/lib/weak_property.dart"
+          "_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": [
-          "../../runtime/lib/async_patch.dart",
-          "../../runtime/lib/deferred_load_patch.dart",
-          "../../runtime/lib/schedule_microtask_patch.dart",
-          "../../runtime/lib/timer_patch.dart"
+          "_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": [
-          "../../runtime/lib/collection_patch.dart",
-          "../../runtime/lib/compact_hash.dart"
+          "_internal/vm/lib/collection_patch.dart",
+          "_internal/vm/lib/compact_hash.dart"
         ],
         "uri": "collection/collection.dart"
       },
       "ffi": {
         "patches": [
-          "../../runtime/lib/ffi_patch.dart",
-          "../../runtime/lib/ffi_dynamic_library_patch.dart",
-          "../../runtime/lib/ffi_native_type_patch.dart"
+          "_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"
       },
-      "wasm": {
-        "patches": [
-          "../../runtime/lib/wasm_patch.dart"
-        ],
-        "uri": "wasm/wasm.dart"
-      },
       "typed_data": {
-        "patches": "../../runtime/lib/typed_data_patch.dart",
+        "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": [
-          "../../runtime/lib/developer.dart",
-          "../../runtime/lib/profiler.dart",
-          "../../runtime/lib/timeline.dart"
+          "_internal/vm/lib/developer.dart",
+          "_internal/vm/lib/profiler.dart",
+          "_internal/vm/lib/timeline.dart"
         ],
         "uri": "developer/developer.dart"
       },
       "isolate": {
         "patches": [
-          "../../runtime/lib/isolate_patch.dart",
-          "../../runtime/lib/timer_impl.dart"
+          "_internal/vm/lib/isolate_patch.dart",
+          "_internal/vm/lib/timer_impl.dart"
         ],
         "uri": "isolate/isolate.dart"
       },
-      "mirrors": {
-        "patches": [
-          "../../runtime/lib/mirrors_patch.dart",
-          "../../runtime/lib/mirrors_impl.dart",
-          "../../runtime/lib/mirror_reference.dart"
-        ],
-        "uri": "mirrors/mirrors.dart"
-      },
       "_vmservice": {
         "uri": "vmservice/vmservice.dart"
       },
+      "wasm": {
+        "patches": [
+          "_internal/vm/lib/wasm_patch.dart"
+        ],
+        "uri": "wasm/wasm.dart"
+      },
       "io": {
         "patches": [
-          "../../runtime/bin/common_patch.dart",
-          "../../runtime/bin/directory_patch.dart",
-          "../../runtime/bin/eventhandler_patch.dart",
-          "../../runtime/bin/file_patch.dart",
-          "../../runtime/bin/file_system_entity_patch.dart",
-          "../../runtime/bin/filter_patch.dart",
-          "../../runtime/bin/io_service_patch.dart",
-          "../../runtime/bin/namespace_patch.dart",
-          "../../runtime/bin/platform_patch.dart",
-          "../../runtime/bin/process_patch.dart",
-          "../../runtime/bin/socket_patch.dart",
-          "../../runtime/bin/stdio_patch.dart",
-          "../../runtime/bin/secure_socket_patch.dart",
-          "../../runtime/bin/sync_socket_patch.dart"
+          "_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": [
-          "../../runtime/lib/internal_patch.dart",
-          "../../runtime/lib/class_id_fasta.dart",
-          "../../runtime/lib/print_patch.dart",
-          "../../runtime/lib/symbol_patch.dart",
+          "_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": "../../runtime/lib/convert_patch.dart",
+        "patches": "_internal/vm/lib/convert_patch.dart",
         "uri": "convert/convert.dart"
       },
       "profiler": {
         "uri": "profiler/profiler.dart"
       },
       "math": {
-        "patches": "../../runtime/lib/math_patch.dart",
+        "patches": "_internal/vm/lib/math_patch.dart",
         "uri": "math/math.dart"
       },
       "_http": {
@@ -487,4 +487,4 @@
       }
     }
   }
-}
+}
\ No newline at end of file
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index f33a42b..a4358e5 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -17,87 +17,87 @@
 vm:
   libraries:
     _builtin:
-      uri: "../../runtime/bin/builtin.dart"
+      uri: "_internal/vm/bin/builtin.dart"
 
     _internal:
       uri: "internal/internal.dart"
       patches:
-        - "../../runtime/lib/internal_patch.dart"
-        - "../../runtime/lib/class_id_fasta.dart"
-        - "../../runtime/lib/print_patch.dart"
-        - "../../runtime/lib/symbol_patch.dart"
+        - "_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"
 
     async:
       uri: "async/async.dart"
       patches:
-        - "../../runtime/lib/async_patch.dart"
-        - "../../runtime/lib/deferred_load_patch.dart"
-        - "../../runtime/lib/schedule_microtask_patch.dart"
-        - "../../runtime/lib/timer_patch.dart"
+        - "_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"
 
     collection:
       uri: "collection/collection.dart"
       patches:
-        - "../../runtime/lib/collection_patch.dart"
-        - "../../runtime/lib/compact_hash.dart"
+        - "_internal/vm/lib/collection_patch.dart"
+        - "_internal/vm/lib/compact_hash.dart"
 
     convert:
       uri: "convert/convert.dart"
-      patches: "../../runtime/lib/convert_patch.dart"
+      patches: "_internal/vm/lib/convert_patch.dart"
 
     core:
       uri: "core/core.dart"
       patches:
-        - "../../runtime/lib/core_patch.dart"
-        - "../../runtime/lib/array.dart"
-        - "../../runtime/lib/array_patch.dart"
-        - "../../runtime/lib/bigint_patch.dart"
-        - "../../runtime/lib/bool_patch.dart"
-        - "../../runtime/lib/date_patch.dart"
-        - "../../runtime/lib/double.dart"
-        - "../../runtime/lib/double_patch.dart"
-        - "../../runtime/lib/errors_patch.dart"
-        - "../../runtime/lib/expando_patch.dart"
-        - "../../runtime/lib/function.dart"
-        - "../../runtime/lib/function_patch.dart"
-        - "../../runtime/lib/growable_array.dart"
-        - "../../runtime/lib/identical_patch.dart"
-        - "../../runtime/lib/immutable_map.dart"
-        - "../../runtime/lib/integers.dart"
-        - "../../runtime/lib/integers_patch.dart"
-        - "../../runtime/lib/invocation_mirror_patch.dart"
-        - "../../runtime/lib/lib_prefix.dart"
-        - "../../runtime/lib/map_patch.dart"
-        - "../../runtime/lib/null_patch.dart"
-        - "../../runtime/lib/object_patch.dart"
-        - "../../runtime/lib/regexp_patch.dart"
-        - "../../runtime/lib/stacktrace.dart"
-        - "../../runtime/lib/stopwatch_patch.dart"
-        - "../../runtime/lib/string_buffer_patch.dart"
-        - "../../runtime/lib/string_patch.dart"
-        - "../../runtime/lib/type_patch.dart"
-        - "../../runtime/lib/uri_patch.dart"
-        - "../../runtime/lib/weak_property.dart"
+        - "_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"
 
     developer:
       uri: "developer/developer.dart"
       patches:
-        - "../../runtime/lib/developer.dart"
-        - "../../runtime/lib/profiler.dart"
-        - "../../runtime/lib/timeline.dart"
+        - "_internal/vm/lib/developer.dart"
+        - "_internal/vm/lib/profiler.dart"
+        - "_internal/vm/lib/timeline.dart"
 
     ffi:
       uri: "ffi/ffi.dart"
       patches:
-        - "../../runtime/lib/ffi_patch.dart"
-        - "../../runtime/lib/ffi_dynamic_library_patch.dart"
-        - "../../runtime/lib/ffi_native_type_patch.dart"
+        - "_internal/vm/lib/ffi_patch.dart"
+        - "_internal/vm/lib/ffi_dynamic_library_patch.dart"
+        - "_internal/vm/lib/ffi_native_type_patch.dart"
 
     wasm:
       uri: "wasm/wasm.dart"
       patches:
-        - "../../runtime/lib/wasm_patch.dart"
+        - "_internal/vm/lib/wasm_patch.dart"
 
     _http:
       uri: "_http/http.dart"
@@ -105,37 +105,37 @@
     io:
       uri: "io/io.dart"
       patches:
-        - "../../runtime/bin/common_patch.dart"
-        - "../../runtime/bin/directory_patch.dart"
-        - "../../runtime/bin/eventhandler_patch.dart"
-        - "../../runtime/bin/file_patch.dart"
-        - "../../runtime/bin/file_system_entity_patch.dart"
-        - "../../runtime/bin/filter_patch.dart"
-        - "../../runtime/bin/io_service_patch.dart"
-        - "../../runtime/bin/namespace_patch.dart"
-        - "../../runtime/bin/platform_patch.dart"
-        - "../../runtime/bin/process_patch.dart"
-        - "../../runtime/bin/socket_patch.dart"
-        - "../../runtime/bin/stdio_patch.dart"
-        - "../../runtime/bin/secure_socket_patch.dart"
-        - "../../runtime/bin/sync_socket_patch.dart"
+        - "_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"
 
     isolate:
       uri: "isolate/isolate.dart"
       patches:
-        - "../../runtime/lib/isolate_patch.dart"
-        - "../../runtime/lib/timer_impl.dart"
+        - "_internal/vm/lib/isolate_patch.dart"
+        - "_internal/vm/lib/timer_impl.dart"
 
     math:
       uri: "math/math.dart"
-      patches: "../../runtime/lib/math_patch.dart"
+      patches: "_internal/vm/lib/math_patch.dart"
 
     mirrors:
       uri: "mirrors/mirrors.dart"
       patches:
-        - "../../runtime/lib/mirrors_patch.dart"
-        - "../../runtime/lib/mirrors_impl.dart"
-        - "../../runtime/lib/mirror_reference.dart"
+        - "_internal/vm/lib/mirrors_patch.dart"
+        - "_internal/vm/lib/mirrors_impl.dart"
+        - "_internal/vm/lib/mirror_reference.dart"
 
     nativewrappers:
       uri: "html/dartium/nativewrappers.dart"
@@ -146,11 +146,11 @@
     cli:
       uri: "cli/cli.dart"
       patches:
-        - "../../runtime/bin/cli_patch.dart"
+        - "_internal/vm/bin/cli_patch.dart"
 
     typed_data:
       uri: "typed_data/typed_data.dart"
-      patches: "../../runtime/lib/typed_data_patch.dart"
+      patches: "_internal/vm/lib/typed_data_patch.dart"
 
     _vmservice:
       uri: "vmservice/vmservice.dart"
diff --git a/sdk/lib/profiler/profiler.dart b/sdk/lib/profiler/profiler.dart
deleted file mode 100644
index 1b96dfe..0000000
--- a/sdk/lib/profiler/profiler.dart
+++ /dev/null
@@ -1,10 +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.
-
-/// Please see 'dart:developer'.
-@Deprecated("Dart SDK 1.12")
-library dart.profiler;
-
-export 'dart:developer'
-    show getCurrentTag, Counter, Gauge, Metric, Metrics, UserTag;
diff --git a/sdk/lib/profiler/profiler_sources.gni b/sdk/lib/profiler/profiler_sources.gni
deleted file mode 100644
index adbf447..0000000
--- a/sdk/lib/profiler/profiler_sources.gni
+++ /dev/null
@@ -1,8 +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.
-
-profiler_sdk_sources = [
-  "profiler.dart",
-  # The above file needs to be first if additional parts are added to the lib.
-]
diff --git a/sdk/lib/wasm/wasm.dart b/sdk/lib/wasm/wasm.dart
index edf0887..a9a09cc 100644
--- a/sdk/lib/wasm/wasm.dart
+++ b/sdk/lib/wasm/wasm.dart
@@ -6,8 +6,76 @@
 /// {@nodoc}
 library dart.wasm;
 
-int callWasm(String name, int arg) {
-  return _callWasm(name, arg);
+import 'dart:typed_data';
+
+// Represents the WASM 32-bit int type.
+class Int32 {}
+
+// Represents the WASM 64-bit int type.
+class Int64 {}
+
+// Represents the WASM 32-bit float type.
+class Float {}
+
+// Represents the WASM 64-bit float type.
+class Double {}
+
+// Represents the return type of a void function in WASM.
+class Void {}
+
+// WasmModule is a compiled module that can be instantiated.
+abstract class WasmModule {
+  // Compile a module.
+  external factory WasmModule(Uint8List data);
+
+  // Instantiate the module with the given imports.
+  WasmInstance instantiate(WasmImports imports);
 }
 
-external int _callWasm(String name, int arg);
+// WasmImports holds all the imports for a WasmInstance.
+abstract class WasmImports {
+  // Create an imports object.
+  external factory WasmImports(String moduleName);
+
+  // Add a global variable to the imports.
+  void addGlobal<T>(String name, num value, bool mutable);
+
+  // Add a memory to the imports.
+  void addMemory(String name, WasmMemory memory);
+}
+
+// WasmMemory is a sandbox for a WasmInstance to run in.
+abstract class WasmMemory {
+  // Create a new memory with the given number of initial pages, and optional
+  // maximum number of pages.
+  external factory WasmMemory(int initialPages, [int maxPages]);
+
+  // The WASM spec defines the page size as 64KiB.
+  static const int kPageSizeInBytes = 64 * 1024;
+
+  // Returns the length of the memory in pages.
+  int get lengthInPages;
+
+  // Returns the length of the memory in bytes.
+  int get lengthInBytes;
+
+  // Returns the byte at the given index.
+  int operator [](int index);
+
+  // Sets the byte at the iven index to value.
+  void operator []=(int index, int value);
+
+  // Grow the memory by deltaPages. Returns the number of pages before resizing.
+  int grow(int deltaPages);
+}
+
+// WasmInstance is an instantiated WasmModule.
+abstract class WasmInstance {
+  // Find an exported function with the given signature.
+  WasmFunction<T> lookupFunction<T extends Function>(String name);
+}
+
+// WasmFunction is a callable function in a WasmInstance.
+abstract class WasmFunction<T extends Function> {
+  num call(List<num> args);
+}
diff --git a/sdk_nnbd/BUILD.gn b/sdk_nnbd/BUILD.gn
index 228fc3c..9a4a1c5 100644
--- a/sdk_nnbd/BUILD.gn
+++ b/sdk_nnbd/BUILD.gn
@@ -134,20 +134,16 @@
   ],
 ]
 if (create_kernel_service_snapshot) {
-  _platform_sdk_snapshots += [
-    [
-      "kernel-service",
-      "../utils/kernel-service:kernel-service_snapshot",
-    ],
-  ]
+  _platform_sdk_snapshots += [ [
+        "kernel-service",
+        "../utils/kernel-service:kernel-service_snapshot",
+      ] ]
 }
 if (dart_target_arch != "arm") {
-  _platform_sdk_snapshots += [
-    [
-      "analysis_server",
-      "../utils/analysis_server",
-    ],
-  ]
+  _platform_sdk_snapshots += [ [
+        "analysis_server",
+        "../utils/analysis_server",
+      ] ]
 }
 
 _full_sdk_snapshots = [
@@ -185,20 +181,16 @@
   ],
 ]
 if (create_kernel_service_snapshot) {
-  _full_sdk_snapshots += [
-    [
-      "kernel-service",
-      "../utils/kernel-service:kernel-service_snapshot",
-    ],
-  ]
+  _full_sdk_snapshots += [ [
+        "kernel-service",
+        "../utils/kernel-service:kernel-service_snapshot",
+      ] ]
 }
 if (dart_target_arch != "arm") {
-  _full_sdk_snapshots += [
-    [
-      "analysis_server",
-      "../utils/analysis_server",
-    ],
-  ]
+  _full_sdk_snapshots += [ [
+        "analysis_server",
+        "../utils/analysis_server",
+      ] ]
 }
 
 # Libraries that go under lib/
@@ -222,7 +214,6 @@
   "js_util",
   "math",
   "mirrors",
-  "profiler",
   "svg",
   "typed_data",
   "wasm",
@@ -249,7 +240,6 @@
 #   "isolate",
 #   "math",
 #   "mirrors",
-#   "profiler",
 #   "typed_data",
 # ]
 _platform_sdk_libraries = _full_sdk_libraries
@@ -260,74 +250,82 @@
 
 # This rule copies dartdoc templates to
 # bin/resources/dartdoc/templates
-copy_tree_specs += [ {
-      target = "copy_dartdoc_templates"
-      visibility = [ ":copy_dartdoc_files" ]
-      source = "../third_party/pkg/dartdoc/lib/templates"
-      dest = "$root_out_dir/dart-sdk/bin/resources/dartdoc/templates"
-      ignore_patterns = "{}"
-    } ]
+copy_tree_specs += [
+  {
+    target = "copy_dartdoc_templates"
+    visibility = [ ":copy_dartdoc_files" ]
+    source = "../third_party/pkg/dartdoc/lib/templates"
+    dest = "$root_out_dir/dart-sdk/bin/resources/dartdoc/templates"
+    ignore_patterns = "{}"
+  },
+]
 
 # This rule copies dartdoc resources to
 # bin/resources/dartdoc/resources
-copy_tree_specs += [ {
-      target = "copy_dartdoc_resources"
-      visibility = [ ":copy_dartdoc_files" ]
-      source = "../third_party/pkg/dartdoc/lib/resources"
-      dest = "$root_out_dir/dart-sdk/bin/resources/dartdoc/resources"
-      ignore_patterns = "{}"
-    } ]
+copy_tree_specs += [
+  {
+    target = "copy_dartdoc_resources"
+    visibility = [ ":copy_dartdoc_files" ]
+    source = "../third_party/pkg/dartdoc/lib/resources"
+    dest = "$root_out_dir/dart-sdk/bin/resources/dartdoc/resources"
+    ignore_patterns = "{}"
+  },
+]
 
 # This loop generates rules to copy libraries to lib/
 foreach(library, _full_sdk_libraries) {
-  copy_tree_specs += [ {
-        target = "copy_${library}_library"
-        visibility = [
-          ":copy_platform_sdk_libraries",
-          ":copy_full_sdk_libraries",
-        ]
-        source = "lib/$library"
-        dest = "$root_out_dir/dart-sdk/lib/$library"
-        ignore_patterns = "*.svn,doc,*.py,*.gypi,*.sh,.gitignore"
-      } ]
+  copy_tree_specs += [
+    {
+      target = "copy_${library}_library"
+      visibility = [
+        ":copy_platform_sdk_libraries",
+        ":copy_full_sdk_libraries",
+      ]
+      source = "lib/$library"
+      dest = "$root_out_dir/dart-sdk/lib/$library"
+      ignore_patterns = "*.svn,doc,*.py,*.gypi,*.sh,.gitignore"
+    },
+  ]
 }
 
 if (is_win) {
-  copy_tree_specs += [ {
-        target = "copy_7zip"
-        visibility = [ ":create_common_sdk" ]
-        deps = [
-          ":copy_libraries",
-        ]
-        source = "../third_party/7zip"
-        dest = "$root_out_dir/dart-sdk/lib/_internal/pub/asset/7zip"
-        ignore_patterns = ".svn"
-      } ]
+  copy_tree_specs += [
+    {
+      target = "copy_7zip"
+      visibility = [ ":create_common_sdk" ]
+      deps = [
+        ":copy_libraries",
+      ]
+      source = "../third_party/7zip"
+      dest = "$root_out_dir/dart-sdk/lib/_internal/pub/asset/7zip"
+      ignore_patterns = ".svn"
+    },
+  ]
 }
 
 if (target_cpu == "x64") {
   copy_tree_specs += [
-      {
-        target = "copy_language_model"
-        visibility = [ ":create_common_sdk" ]
-        deps = [
-          ":copy_libraries",
-        ]
-        source = "../pkg/analysis_server/language_model"
-        dest = "$root_out_dir/dart-sdk/model"
-        ignore_patterns = "{}"
-      },
-      {
-        target = "copy_libtensorflowlite_c"
-        visibility = [ ":create_common_sdk" ]
-        deps = [
-          ":copy_libraries",
-        ]
-        source = "../third_party/pkg/tflite_native/lib/src/blobs"
-        dest = "$root_out_dir/dart-sdk/bin/snapshots"
-        ignore_patterns = "{}"
-      }
-   ]
+    {
+      target = "copy_language_model"
+      visibility = [ ":create_common_sdk" ]
+      deps = [
+        ":copy_libraries",
+      ]
+      source = "../pkg/analysis_server/language_model"
+      dest = "$root_out_dir/dart-sdk/model"
+      ignore_patterns = "{}"
+    },
+    {
+      target = "copy_libtensorflowlite_c"
+      visibility = [ ":create_common_sdk" ]
+      deps = [
+        ":copy_libraries",
+      ]
+      source = "../third_party/pkg/tflite_native/lib/src/blobs"
+      dest = "$root_out_dir/dart-sdk/bin/snapshots"
+      ignore_patterns = "{}"
+    },
+  ]
 }
 
 # This generates targets for everything in copy_tree_specs. The targets have the
@@ -399,7 +397,8 @@
   deps = [
     "../runtime/bin:dartaotruntime",
   ]
-  dartaotruntime_out = get_label_info("../runtime/bin:dartaotruntime", "root_out_dir")
+  dartaotruntime_out =
+      get_label_info("../runtime/bin:dartaotruntime", "root_out_dir")
   if (is_win) {
     sources = [
       "$dartaotruntime_out/dartaotruntime.exe",
@@ -421,7 +420,8 @@
   deps = [
     "../runtime/bin:gen_snapshot",
   ]
-  gen_snapshot_out = get_label_info("../runtime/bin:gen_snapshot", "root_out_dir")
+  gen_snapshot_out =
+      get_label_info("../runtime/bin:gen_snapshot", "root_out_dir")
   if (is_win) {
     sources = [
       "$gen_snapshot_out/gen_snapshot.exe",
@@ -663,8 +663,8 @@
   visibility = [ ":copy_dev_compiler_sdk" ]
   deps = [
     ":copy_libraries",
-    "../utils/dartdevc:dartdevc_sdk",
     "../utils/dartdevc:dartdevc_kernel_sdk_outline",
+    "../utils/dartdevc:dartdevc_sdk",
   ]
   gen_dir = get_label_info("../utils/dartdevc:dartdevc_sdk", "target_gen_dir")
   sources = [
@@ -736,8 +736,8 @@
   deps = [
     "../utils/dartdevc:dartdevc_kernel_sdk",
   ]
-  gen_dir = get_label_info("../utils/dartdevc:dartdevc_kernel_sdk",
-                           "target_gen_dir")
+  gen_dir =
+      get_label_info("../utils/dartdevc:dartdevc_kernel_sdk", "target_gen_dir")
   sources = [
     "$gen_dir/kernel/amd/dart_sdk.js",
     "$gen_dir/kernel/amd/dart_sdk.js.map",
@@ -754,8 +754,8 @@
   deps = [
     "../utils/dartdevc:dartdevc_kernel_sdk",
   ]
-  gen_dir = get_label_info("../utils/dartdevc:dartdevc_kernel_sdk",
-                           "target_gen_dir")
+  gen_dir =
+      get_label_info("../utils/dartdevc:dartdevc_kernel_sdk", "target_gen_dir")
   sources = [
     "$gen_dir/kernel/common/dart_sdk.js",
     "$gen_dir/kernel/common/dart_sdk.js.map",
@@ -772,8 +772,8 @@
   deps = [
     "../utils/dartdevc:dartdevc_kernel_sdk",
   ]
-  gen_dir = get_label_info("../utils/dartdevc:dartdevc_kernel_sdk",
-                           "target_gen_dir")
+  gen_dir =
+      get_label_info("../utils/dartdevc:dartdevc_kernel_sdk", "target_gen_dir")
   sources = [
     "$gen_dir/kernel/es6/dart_sdk.js",
     "$gen_dir/kernel/es6/dart_sdk.js.map",
@@ -1006,8 +1006,8 @@
     ":copy_dartdoc_files",
     ":copy_headers",
     ":copy_libraries_dart",
-    ":copy_license",
     ":copy_libraries_specification",
+    ":copy_license",
     ":copy_readme",
     ":copy_vm_dill_files",
     ":write_dartdoc_options",
diff --git a/sdk_nnbd/lib/_chrome/dart2js/chrome_dart2js.dart b/sdk_nnbd/lib/_chrome/dart2js/chrome_dart2js.dart
index 023afe4..c9a9735 100644
--- a/sdk_nnbd/lib/_chrome/dart2js/chrome_dart2js.dart
+++ b/sdk_nnbd/lib/_chrome/dart2js/chrome_dart2js.dart
@@ -5,6 +5,8 @@
 ///
 /// For more information on these APIs, see the
 /// [chrome.* API documentation](http://developer.chrome.com/apps/api_index.html).
+// @dart = 2.5
+
 library _chrome;
 
 import 'dart:_foreign_helper' show JS;
diff --git a/sdk_nnbd/lib/_http/crypto.dart b/sdk_nnbd/lib/_http/crypto.dart
index 28b65ee..0efbe45 100644
--- a/sdk_nnbd/lib/_http/crypto.dart
+++ b/sdk_nnbd/lib/_http/crypto.dart
@@ -2,6 +2,8 @@
 // for details. All 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._http;
 
 class _CryptoUtils {
diff --git a/sdk_nnbd/lib/_http/http.dart b/sdk_nnbd/lib/_http/http.dart
index 2fc751f..2689758 100644
--- a/sdk_nnbd/lib/_http/http.dart
+++ b/sdk_nnbd/lib/_http/http.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 library dart._http;
 
 import 'dart:async';
diff --git a/sdk_nnbd/lib/_http/http_date.dart b/sdk_nnbd/lib/_http/http_date.dart
index d9301b4..80b0397 100644
--- a/sdk_nnbd/lib/_http/http_date.dart
+++ b/sdk_nnbd/lib/_http/http_date.dart
@@ -2,6 +2,8 @@
 // for details. All 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._http;
 
 /**
diff --git a/sdk_nnbd/lib/_http/http_headers.dart b/sdk_nnbd/lib/_http/http_headers.dart
index 7601485..58fe2af 100644
--- a/sdk_nnbd/lib/_http/http_headers.dart
+++ b/sdk_nnbd/lib/_http/http_headers.dart
@@ -2,6 +2,8 @@
 // for details. All 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._http;
 
 class _HttpHeaders implements HttpHeaders {
diff --git a/sdk_nnbd/lib/_http/http_impl.dart b/sdk_nnbd/lib/_http/http_impl.dart
index cdf2412..9741981 100644
--- a/sdk_nnbd/lib/_http/http_impl.dart
+++ b/sdk_nnbd/lib/_http/http_impl.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart._http;
 
 int _nextServiceId = 1;
diff --git a/sdk_nnbd/lib/_http/http_parser.dart b/sdk_nnbd/lib/_http/http_parser.dart
index bd85b2b..f3c619d 100644
--- a/sdk_nnbd/lib/_http/http_parser.dart
+++ b/sdk_nnbd/lib/_http/http_parser.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart._http;
 
 // Global constants.
diff --git a/sdk_nnbd/lib/_http/http_session.dart b/sdk_nnbd/lib/_http/http_session.dart
index 3907609..0cffefe 100644
--- a/sdk_nnbd/lib/_http/http_session.dart
+++ b/sdk_nnbd/lib/_http/http_session.dart
@@ -2,6 +2,8 @@
 // for details. All 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._http;
 
 const String _DART_SESSION_ID = "DARTSESSID";
diff --git a/sdk_nnbd/lib/_http/overrides.dart b/sdk_nnbd/lib/_http/overrides.dart
index 7f9e689..962a009 100644
--- a/sdk_nnbd/lib/_http/overrides.dart
+++ b/sdk_nnbd/lib/_http/overrides.dart
@@ -2,6 +2,8 @@
 // for details. All 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._http;
 
 final _httpOverridesToken = new Object();
diff --git a/sdk_nnbd/lib/_http/websocket.dart b/sdk_nnbd/lib/_http/websocket.dart
index 5a949af..8faa0e1 100644
--- a/sdk_nnbd/lib/_http/websocket.dart
+++ b/sdk_nnbd/lib/_http/websocket.dart
@@ -2,6 +2,8 @@
 // for details. All 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._http;
 
 /**
diff --git a/sdk_nnbd/lib/_http/websocket_impl.dart b/sdk_nnbd/lib/_http/websocket_impl.dart
index 8750ccc..c3e8bc4 100644
--- a/sdk_nnbd/lib/_http/websocket_impl.dart
+++ b/sdk_nnbd/lib/_http/websocket_impl.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart._http;
 
 const String _webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
@@ -601,11 +603,11 @@
     data.addAll(const [0x00, 0x00, 0xff, 0xff]);
 
     decoder.process(data, 0, data.length);
-    var result = <int>[];
+    final result = new BytesBuilder();
     List<int> out;
 
     while ((out = decoder.processed()) != null) {
-      result.addAll(out);
+      result.add(out);
     }
 
     if ((serverSide && clientNoContextTakeover) ||
@@ -613,7 +615,7 @@
       decoder = null;
     }
 
-    return new Uint8List.fromList(result);
+    return result.takeBytes();
   }
 
   List<int> processOutgoingMessage(List<int> msg) {
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart
index 91d6847..42d4c42 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart
@@ -2,89 +2,90 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/**
- * Support for interoperating with JavaScript.
- *
- * This library provides access to JavaScript objects from Dart, allowing
- * Dart code to get and set properties, and call methods of JavaScript objects
- * and invoke JavaScript functions. The library takes care of converting
- * between Dart and JavaScript objects where possible, or providing proxies if
- * conversion isn't possible.
- *
- * This library does not yet make Dart objects usable from JavaScript, their
- * methods and proeprties are not accessible, though it does allow Dart
- * functions to be passed into and called from JavaScript.
- *
- * [JsObject] is the core type and represents a proxy of a JavaScript object.
- * JsObject gives access to the underlying JavaScript objects properties and
- * methods. `JsObject`s can be acquired by calls to JavaScript, or they can be
- * created from proxies to JavaScript constructors.
- *
- * The top-level getter [context] provides a [JsObject] that represents the
- * global object in JavaScript, usually `window`.
- *
- * The following example shows an alert dialog via a JavaScript call to the
- * global function `alert()`:
- *
- *     import 'dart:js';
- *
- *     main() => context.callMethod('alert', ['Hello from Dart!']);
- *
- * This example shows how to create a [JsObject] from a JavaScript constructor
- * and access its properties:
- *
- *     import 'dart:js';
- *
- *     main() {
- *       var object = new JsObject(context['Object']);
- *       object['greeting'] = 'Hello';
- *       object['greet'] = (name) => "${object['greeting']} $name";
- *       var message = object.callMethod('greet', ['JavaScript']);
- *       context['console'].callMethod('log', [message]);
- *     }
- *
- * ## Proxying and automatic conversion
- *
- * When setting properties on a JsObject or passing arguments to a Javascript
- * method or function, Dart objects are automatically converted or proxied to
- * JavaScript objects. When accessing JavaScript properties, or when a Dart
- * closure is invoked from JavaScript, the JavaScript objects are also
- * converted to Dart.
- *
- * Functions and closures are proxied in such a way that they are callable. A
- * Dart closure assigned to a JavaScript property is proxied by a function in
- * JavaScript. A JavaScript function accessed from Dart is proxied by a
- * [JsFunction], which has a [apply] method to invoke it.
- *
- * The following types are transferred directly and not proxied:
- *
- * * "Basic" types: `null`, `bool`, `num`, `String`, `DateTime`
- * * `Blob`
- * * `Event`
- * * `HtmlCollection`
- * * `ImageData`
- * * `KeyRange`
- * * `Node`
- * * `NodeList`
- * * `TypedData`, including its subclasses like `Int32List`, but _not_
- *   `ByteBuffer`
- * * `Window`
- *
- * ## Converting collections with JsObject.jsify()
- *
- * To create a JavaScript collection from a Dart collection use the
- * [JsObject.jsify] constructor, which converts Dart [Map]s and [Iterable]s
- * into JavaScript Objects and Arrays.
- *
- * The following expression creates a new JavaScript object with the properties
- * `a` and `b` defined:
- *
- *     var jsMap = new JsObject.jsify({'a': 1, 'b': 2});
- *
- * This expression creates a JavaScript array:
- *
- *     var jsArray = new JsObject.jsify([1, 2, 3]);
- */
+// @dart = 2.5
+
+// DDC version of sdk/lib/js/dart2js/js_dart2js.dart
+
+/// Low-level support for interoperating with JavaScript.
+///
+/// You should usually use `package:js` instead of this library. For more
+/// information, see the [JS interop page](https://dart.dev/web/js-interop).
+///
+/// This library provides access to JavaScript objects from Dart, allowing
+/// Dart code to get and set properties, and call methods of JavaScript objects
+/// and invoke JavaScript functions. The library takes care of converting
+/// between Dart and JavaScript objects where possible, or providing proxies if
+/// conversion isn't possible.
+///
+/// This library does not make Dart objects usable from JavaScript, their
+/// methods and properties are not accessible, though it does allow Dart
+/// functions to be passed into and called from JavaScript.
+///
+/// [JsObject] is the core type and represents a proxy of a JavaScript object.
+/// JsObject gives access to the underlying JavaScript objects properties and
+/// methods. `JsObject`s can be acquired by calls to JavaScript, or they can be
+/// created from proxies to JavaScript constructors.
+///
+/// The top-level getter [context] provides a [JsObject] that represents the
+/// global object in JavaScript, usually `window`.
+///
+/// The following example shows an alert dialog via a JavaScript call to the
+/// global function `alert()`:
+///
+///     import 'dart:js';
+///
+///     main() => context.callMethod('alert', ['Hello from Dart!']);
+///
+/// This example shows how to create a [JsObject] from a JavaScript constructor
+/// and access its properties:
+///
+///     import 'dart:js';
+///
+///     main() {
+///       var object = JsObject(context['Object']);
+///       object['greeting'] = 'Hello';
+///       object['greet'] = (name) => "${object['greeting']} $name";
+///       var message = object.callMethod('greet', ['JavaScript']);
+///       context['console'].callMethod('log', [message]);
+///     }
+///
+/// ## Proxying and automatic conversion
+///
+/// When setting properties on a JsObject or passing arguments to a Javascript
+/// method or function, Dart objects are automatically converted or proxied to
+/// JavaScript objects. When accessing JavaScript properties, or when a Dart
+/// closure is invoked from JavaScript, the JavaScript objects are also
+/// converted to Dart.
+///
+/// Functions and closures are proxied in such a way that they are callable. A
+/// Dart closure assigned to a JavaScript property is proxied by a function in
+/// JavaScript. A JavaScript function accessed from Dart is proxied by a
+/// [JsFunction], which has a [apply] method to invoke it.
+///
+/// The following types are transferred directly and not proxied:
+///
+///   * Basic types: `null`, `bool`, `num`, `String`, `DateTime`
+///   * `TypedData`, including its subclasses like `Int32List`, but _not_
+///     `ByteBuffer`
+///   * When compiling for the web, also: `Blob`, `Event`, `ImageData`,
+///     `KeyRange`, `Node`, and `Window`.
+///
+/// ## Converting collections with JsObject.jsify()
+///
+/// To create a JavaScript collection from a Dart collection use the
+/// [JsObject.jsify] constructor, which converts Dart [Map]s and [Iterable]s
+/// into JavaScript Objects and Arrays.
+///
+/// The following expression creates a new JavaScript object with the properties
+/// `a` and `b` defined:
+///
+///     var jsMap = JsObject.jsify({'a': 1, 'b': 2});
+///
+/// This expression creates a JavaScript array:
+///
+///     var jsArray = JsObject.jsify([1, 2, 3]);
+///
+/// {@category Web}
 library dart.js;
 
 import 'dart:collection' show HashMap, ListMixin;
@@ -93,14 +94,13 @@
 import 'dart:_foreign_helper' show JS;
 import 'dart:_runtime' as dart;
 
+/// The JavaScript global object, usually `window`.
 final JsObject context = _wrapToDart(dart.global_);
 
-/**
- * Proxies a JavaScript object to Dart.
- *
- * The properties of the JavaScript object are accessible via the `[]` and
- * `[]=` operators. Methods are callable via [callMethod].
- */
+/// A proxy on a JavaScript object.
+///
+/// The properties of the JavaScript object are accessible via the `[]` and
+/// `[]=` operators. Methods are callable via [callMethod].
 class JsObject {
   // The wrapped JS object.
   final dynamic _jsObject;
@@ -110,10 +110,8 @@
     assert(_jsObject != null);
   }
 
-  /**
-   * Constructs a new JavaScript object from [constructor] and returns a proxy
-   * to it.
-   */
+  /// Constructs a JavaScript object from its native [constructor] and returns
+  /// a proxy to it.
   factory JsObject(JsFunction constructor, [List arguments]) {
     var ctor = constructor._jsObject;
     if (arguments == null) {
@@ -123,17 +121,15 @@
     return _wrapToDart(JS('', 'new #(...#)', ctor, unwrapped));
   }
 
-  /**
-   * Constructs a [JsObject] that proxies a native Dart object; _for expert use
-   * only_.
-   *
-   * Use this constructor only if you wish to get access to JavaScript
-   * properties attached to a browser host object, such as a Node or Blob, that
-   * is normally automatically converted into a native Dart object.
-   *
-   * An exception will be thrown if [object] either is `null` or has the type
-   * `bool`, `num`, or `String`.
-   */
+  /// Constructs a [JsObject] that proxies a native Dart object; _for expert use
+  /// only_.
+  ///
+  /// Use this constructor only if you wish to get access to JavaScript
+  /// properties attached to a browser host object, such as a Node or Blob, that
+  /// is normally automatically converted into a native Dart object.
+  ///
+  /// An exception will be thrown if [object] either is `null` or has the type
+  /// `bool`, `num`, or `String`.
   factory JsObject.fromBrowserObject(object) {
     if (object is num || object is String || object is bool || object == null) {
       throw ArgumentError("object cannot be a num, string, bool, or null");
@@ -141,15 +137,13 @@
     return _wrapToDart(_convertToJS(object));
   }
 
-  /**
-   * Recursively converts a JSON-like collection of Dart objects to a
-   * collection of JavaScript objects and returns a [JsObject] proxy to it.
-   *
-   * [object] must be a [Map] or [Iterable], the contents of which are also
-   * converted. Maps and Iterables are copied to a new JavaScript object.
-   * Primitives and other transferable values are directly converted to their
-   * JavaScript type, and all other objects are proxied.
-   */
+  /// Recursively converts a JSON-like collection of Dart objects to a
+  /// collection of JavaScript objects and returns a [JsObject] proxy to it.
+  ///
+  /// [object] must be a [Map] or [Iterable], the contents of which are also
+  /// converted. Maps and Iterables are copied to a new JavaScript object.
+  /// Primitives and other transferable values are directly converted to their
+  /// JavaScript type, and all other objects are proxied.
   factory JsObject.jsify(object) {
     if ((object is! Map) && (object is! Iterable)) {
       throw ArgumentError("object must be a Map or Iterable");
@@ -184,12 +178,10 @@
     return _convert(data);
   }
 
-  /**
-   * Returns the value associated with [property] from the proxied JavaScript
-   * object.
-   *
-   * The type of [property] must be either [String] or [num].
-   */
+  /// Returns the value associated with [property] from the proxied JavaScript
+  /// object.
+  ///
+  /// The type of [property] must be either [String] or [num].
   dynamic operator [](Object property) {
     if (property is! String && property is! num) {
       throw ArgumentError("property is not a String or num");
@@ -197,12 +189,10 @@
     return _convertToDart(JS('', '#[#]', _jsObject, property));
   }
 
-  /**
-   * Sets the value associated with [property] on the proxied JavaScript
-   * object.
-   *
-   * The type of [property] must be either [String] or [num].
-   */
+  // Sets the value associated with [property] on the proxied JavaScript
+  // object.
+  //
+  // The type of [property] must be either [String] or [num].
   void operator []=(Object property, value) {
     if (property is! String && property is! num) {
       throw ArgumentError("property is not a String or num");
@@ -215,12 +205,10 @@
   bool operator ==(other) =>
       other is JsObject && JS<bool>('!', '# === #', _jsObject, other._jsObject);
 
-  /**
-   * Returns `true` if the JavaScript object contains the specified property
-   * either directly or though its prototype chain.
-   *
-   * This is the equivalent of the `in` operator in JavaScript.
-   */
+  /// Returns `true` if the JavaScript object contains the specified property
+  /// either directly or though its prototype chain.
+  ///
+  /// This is the equivalent of the `in` operator in JavaScript.
   bool hasProperty(property) {
     if (property is! String && property is! num) {
       throw ArgumentError("property is not a String or num");
@@ -228,11 +216,9 @@
     return JS<bool>('!', '# in #', property, _jsObject);
   }
 
-  /**
-   * Removes [property] from the JavaScript object.
-   *
-   * This is the equivalent of the `delete` operator in JavaScript.
-   */
+  /// Removes [property] from the JavaScript object.
+  ///
+  /// This is the equivalent of the `delete` operator in JavaScript.
   void deleteProperty(property) {
     if (property is! String && property is! num) {
       throw ArgumentError("property is not a String or num");
@@ -240,18 +226,14 @@
     JS<bool>('!', 'delete #[#]', _jsObject, property);
   }
 
-  /**
-   * Returns `true` if the JavaScript object has [type] in its prototype chain.
-   *
-   * This is the equivalent of the `instanceof` operator in JavaScript.
-   */
+  /// Returns `true` if the JavaScript object has [type] in its prototype chain.
+  ///
+  /// This is the equivalent of the `instanceof` operator in JavaScript.
   bool instanceof(JsFunction type) {
     return JS<bool>('!', '# instanceof #', _jsObject, _convertToJS(type));
   }
 
-  /**
-   * Returns the result of the JavaScript objects `toString` method.
-   */
+  /// Returns the result of the JavaScript objects `toString` method.
   String toString() {
     try {
       return JS<String>('!', 'String(#)', _jsObject);
@@ -260,12 +242,10 @@
     }
   }
 
-  /**
-   * Calls [method] on the JavaScript object with the arguments [args] and
-   * returns the result.
-   *
-   * The type of [method] must be either [String] or [num].
-   */
+  /// Calls [method] on the JavaScript object with the arguments [args] and
+  /// returns the result.
+  ///
+  /// The type of [method] must be either [String] or [num].
   dynamic callMethod(method, [List args]) {
     if (method is! String && method is! num) {
       throw ArgumentError("method is not a String or num");
@@ -279,14 +259,10 @@
   }
 }
 
-/**
- * Proxies a JavaScript Function object.
- */
+/// A proxy on a JavaScript Function object.
 class JsFunction extends JsObject {
-  /**
-   * Returns a [JsFunction] that captures its 'this' binding and calls [f]
-   * with the value of this passed as the first argument.
-   */
+  /// Returns a [JsFunction] that captures its 'this' binding and calls [f]
+  /// with the value of JavaScript `this` passed as the first argument.
   factory JsFunction.withThis(Function f) {
     return JsFunction._fromJs(JS(
         '',
@@ -305,10 +281,8 @@
 
   JsFunction._fromJs(jsObject) : super._fromJs(jsObject);
 
-  /**
-   * Invokes the JavaScript function with arguments [args]. If [thisArg] is
-   * supplied it is the value of `this` for the invocation.
-   */
+  /// Invokes the JavaScript function with arguments [args]. If [thisArg] is
+  /// supplied it is the value of `this` for the invocation.
   dynamic apply(List args, {thisArg}) => _convertToDart(JS(
       '',
       '#.apply(#, #)',
@@ -318,17 +292,13 @@
 }
 
 // TODO(jmesserly): this is totally unnecessary in dev_compiler.
-/** A [List] that proxies a JavaScript array. */
+/// A [List] that proxies a JavaScript array.
 class JsArray<E> extends JsObject with ListMixin<E> {
-  /**
-   * Creates a new JavaScript array.
-   */
+  /// Creates an empty JavaScript array.
   JsArray() : super._fromJs([]);
 
-  /**
-   * Creates a new JavaScript array and initializes it to the contents of
-   * [other].
-   */
+  /// Creates a new JavaScript array and initializes it to the contents of
+  /// [other].
   JsArray.from(Iterable<E> other)
       : super._fromJs([]..addAll(other.map(_convertToJS)));
 
@@ -544,16 +514,16 @@
 Expando<Function> _interopExpando = Expando<Function>();
 
 /// Returns a wrapper around function [f] that can be called from JavaScript
-/// using the package:js Dart-JavaScript interop.
+/// using `package:js` JavaScript interop.
 ///
-/// For performance reasons in Dart2Js, by default Dart functions cannot be
-/// passed directly to JavaScript unless this method is called to create
-/// a Function compatible with both Dart and JavaScript.
-/// Calling this method repeatedly on a function will return the same function.
-/// The [Function] returned by this method can be used from both Dart and
-/// JavaScript. We may remove the need to call this method completely in the
-/// future if Dart2Js is refactored so that its function calling conventions
-/// are more compatible with JavaScript.
+/// The calling conventions in Dart2Js differ from JavaScript and so, by
+/// default, it is not possible to call a Dart function directly. Wrapping with
+/// `allowInterop` creates a function that can be called from JavaScript or
+/// Dart. The semantics of the wrapped function are still more strict than
+/// JavaScript, and the function will throw if called with too many or too few
+/// arguments.
+///
+/// Calling this method repeatedly on a function will return the same result.
 F allowInterop<F extends Function>(F f) {
   var ret = _interopExpando[f];
   if (ret == null) {
@@ -571,12 +541,13 @@
 
 Expando<Function> _interopCaptureThisExpando = Expando<Function>();
 
-/// Returns a [Function] that when called from JavaScript captures its 'this'
-/// binding and calls [f] with the value of this passed as the first argument.
-/// When called from Dart, [null] will be passed as the first argument.
+/// Returns a wrapper around function [f] that can be called from JavaScript
+/// using `package:js` JavaScript interop, passing JavaScript `this` as the first
+/// argument.
 ///
-/// See the documentation for [allowInterop]. This method should only be used
-/// with package:js Dart-JavaScript interop.
+/// See [allowInterop].
+///
+/// When called from Dart, [null] will be passed as the first argument.
 Function allowInteropCaptureThis(Function f) {
   var ret = _interopCaptureThisExpando[f];
   if (ret == null) {
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart
index 4b9fdb0..66f8c29 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 /// Utility methods to efficiently manipulate typed JSInterop objects in cases
 /// where the name to call is not known at runtime. You should only use these
 /// methods when the same effect cannot be achieved with @JS annotations.
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/libraries.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/libraries.dart
index d5cffa2..ce023f1 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/libraries.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/libraries.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 library libraries;
 
 /**
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/async_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/async_patch.dart
index 894aef4..88d2407 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/async_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/async_patch.dart
@@ -2,6 +2,8 @@
 // for details. All 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 the dart:async library.
 
 import 'dart:_js_helper' show notNull, patch, ReifyFunctionTypes;
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/cli_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/cli_patch.dart
index b1c3841..266941b 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/cli_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/cli_patch.dart
@@ -2,6 +2,8 @@
 // for details. All 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:_js_helper' show patch;
 
 @patch
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 daa3bf8..d37655d 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,6 +2,8 @@
 // for details. All 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 486473b..637febd 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,6 +2,8 @@
 // for details. All 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 746ac61..7a8ac4b 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,6 +2,8 @@
 // for details. All 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';
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 7f5e4fe..4f2befc 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,6 +2,8 @@
 // for details. All 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/internal_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/internal_patch.dart
index 5e850bb..e642b5c 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/internal_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/internal_patch.dart
@@ -2,6 +2,8 @@
 // for details. All 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:core' hide Symbol;
 import 'dart:core' as core show Symbol;
 import 'dart:_js_primitives' show printString;
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 61d031a..595f4c2 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
@@ -2,6 +2,8 @@
 // for details. All 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:_js_helper' show patch;
 import 'dart:async';
 import 'dart:convert';
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/isolate_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/isolate_patch.dart
index f6aa73bb..cbe69f0 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/isolate_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/isolate_patch.dart
@@ -2,6 +2,8 @@
 // for details. All 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 the dart:isolate library.
 
 import 'dart:_js_helper' show patch, NoReifyGeneric;
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 2ba4220..eb5c568 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,6 +2,8 @@
 // for details. All 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;
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/mirrors_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/mirrors_patch.dart
index e3b015b..9aca3ee 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/mirrors_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/mirrors_patch.dart
@@ -2,6 +2,8 @@
 // for details. All 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 library for dart:mirrors.
 
 import 'dart:_js_helper' show patch;
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 f1e2dc1..a06bd14 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,6 +2,8 @@
 // for details. All 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/annotations.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/annotations.dart
index bc437da..1673fd1 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/annotations.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/annotations.dart
@@ -2,6 +2,8 @@
 // for details. All 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._js_helper;
 
 /// Tells the optimizing compiler to always inline the annotated method.
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/custom_hash_map.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/custom_hash_map.dart
index c7c920d..07fc5c6 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/custom_hash_map.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/custom_hash_map.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart._js_helper;
 
 class CustomKeyHashMap<K, V> extends CustomHashMap<K, V> {
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 8fe2fa6..fb2b5b0 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
@@ -2,6 +2,8 @@
 // for details. All 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
+
 /// This library defines the operations that define and manipulate Dart
 /// classes.  Included in this are:
 ///   - Generics
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart
index f875336..b4ee6a6 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart._runtime;
 
 // We need to set these properties while the sdk is only partially initialized
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 e388cd6..224ba1c 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
@@ -2,6 +2,8 @@
 // for details. All 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
+
 /// This library defines runtime operations on objects used by the code
 /// generator.
 part of dart._runtime;
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 11ea1ae..6ac07ee 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
@@ -2,6 +2,8 @@
 // for details. All 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
+
 /// This library defines the association between runtime objects and
 /// runtime types.
 part of dart._runtime;
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 99e1ab9..198ba6e 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
@@ -2,6 +2,8 @@
 // for details. All 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
+
 @ReifyFunctionTypes(false)
 library dart._runtime;
 
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 3175eeb..5dbff7f 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
@@ -2,6 +2,8 @@
 // for details. All 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
+
 /// This library defines the representation of runtime types.
 part of dart._runtime;
 
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/utils.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/utils.dart
index 2c06179..6313fdd 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/utils.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/utils.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart._runtime;
 
 /// This library defines a set of general javascript utilities for us
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/debugger.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/debugger.dart
index 4618317..8715cbd 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/debugger.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/debugger.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 library dart._debugger;
 
 import 'dart:_foreign_helper' show JS;
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/foreign_helper.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/foreign_helper.dart
index 588d789..c9296cc 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/foreign_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/foreign_helper.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 library dart._foreign_helper;
 
 /**
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/identity_hash_map.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/identity_hash_map.dart
index 04107cc..3918bea 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/identity_hash_map.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/identity_hash_map.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart._js_helper;
 
 class IdentityMap<K, V> extends InternalMap<K, V> {
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/interceptors.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/interceptors.dart
index 6ddd96b..1de2473 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/interceptors.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/interceptors.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 library dart._interceptors;
 
 import 'dart:collection';
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 490c4b9..ad4ec46 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
@@ -2,6 +2,8 @@
 // for details. All 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
+
 library dart._isolate_helper;
 
 import 'dart:_runtime' as dart;
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_array.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_array.dart
index f064b24..1818f08 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_array.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_array.dart
@@ -2,6 +2,8 @@
 // for details. All 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._interceptors;
 
 /**
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_helper.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_helper.dart
index 5d6b037..e86378d 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_helper.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 library dart._js_helper;
 
 import 'dart:collection';
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_mirrors.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_mirrors.dart
index a93f5fb..42db17d 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_mirrors.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_mirrors.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 library dart._js_mirrors;
 
 import 'dart:mirrors';
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_number.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_number.dart
index 5f8c7e0..36350b6 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_number.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_number.dart
@@ -2,6 +2,8 @@
 // for details. All 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._interceptors;
 
 /**
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_primitives.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_primitives.dart
index 1347b62..addcd83 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_primitives.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_primitives.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 /// dart2js "primitives", that is, features that cannot be implemented without
 /// access to JavaScript features.
 library dart2js._js_primitives;
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_rti.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_rti.dart
index 015c83e..37a9644 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_rti.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_rti.dart
@@ -2,6 +2,8 @@
 // for details. All 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._js_helper;
 
 // TODO(leafp): Maybe get rid of this?  Currently used by the interceptors
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_string.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_string.dart
index 4271d34..90e39ae 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_string.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_string.dart
@@ -2,6 +2,8 @@
 // for details. All 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._interceptors;
 
 /**
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/linked_hash_map.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/linked_hash_map.dart
index 1c03db8..04f8a5c 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/linked_hash_map.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/linked_hash_map.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 // Efficient JavaScript based implementation of a linked hash map used as a
 // backing map for constant maps and the [LinkedHashMap] patch
 
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/mirror_helper.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/mirror_helper.dart
index f78926a..96d2da9 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/mirror_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/mirror_helper.dart
@@ -1,6 +1,8 @@
 // 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
+
 /**
  * Helps dealing with reflection in the case that the source code has been
  * changed as a result of compiling with dart2dart.
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/native_helper.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/native_helper.dart
index cc214e8..c36cd41 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/native_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/native_helper.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart._js_helper;
 
 // Obsolete in dart dev compiler. Added only so that the same version of
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 2a7a621..13fc0b5 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,6 +2,8 @@
 // for details. All 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/profile.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/profile.dart
index d46f7f7..8f3410b 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/profile.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/profile.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 /// This file supports profiling dynamic calls.
 part of dart._debugger;
 
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 fadcda0..fb0ee04 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
@@ -2,6 +2,8 @@
 // for details. All 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._js_helper;
 
 // Helper method used by internal libraries.
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/string_helper.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/string_helper.dart
index c1b5c18..81bc0c7 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/string_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/string_helper.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart._js_helper;
 
 @notNull
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/annotations.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/annotations.dart
index f53c5f3..17e1de8 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/annotations.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/annotations.dart
@@ -2,6 +2,8 @@
 // for details. All 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 _js_helper;
 
 /// Marks a class as native and defines its JavaScript name(s).
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/async_patch.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/async_patch.dart
index 68bcbeb..39c2e50 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/async_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/async_patch.dart
@@ -2,6 +2,8 @@
 // for details. All 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 the dart:async library.
 
 import 'dart:_js_helper'
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/cli_patch.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/cli_patch.dart
index 6921e60..e66d4e6 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/cli_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/cli_patch.dart
@@ -2,6 +2,8 @@
 // for details. All 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:_js_helper' show patch;
 
 @patch
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/collection_patch.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/collection_patch.dart
index 300d490..a0cb1b3 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/collection_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/collection_patch.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 import 'dart:_js_helper'
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/constant_map.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/constant_map.dart
index f7c7936..829d620 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/constant_map.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/constant_map.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of _js_helper;
 
 class ConstantMapView<K, V> extends UnmodifiableMapView<K, V>
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/convert_patch.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/convert_patch.dart
index fa6a0b0..bc996be 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/convert_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/convert_patch.dart
@@ -2,6 +2,8 @@
 // for details. All 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_runtime/lib/core_patch.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/core_patch.dart
index c655fc2..3fb8ccd 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/core_patch.dart
@@ -2,6 +2,8 @@
 // for details. All 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" hide Symbol, LinkedList, LinkedListEntry;
 import "dart:_internal" as _symbol_dev;
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/developer_patch.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/developer_patch.dart
index 0ff0f66..719d7d4 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/developer_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/developer_patch.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/foreign_helper.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/foreign_helper.dart
index 0cecf96..6e4b037 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/foreign_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/foreign_helper.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 library _foreign_helper;
 
 import 'dart:_js_embedded_names' show JsGetName, JsBuiltin;
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/instantiation.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/instantiation.dart
index bb003e6..bdc2150 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/instantiation.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/instantiation.dart
@@ -2,6 +2,8 @@
 // for details. All 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 _js_helper;
 
 /// Support class for generic function type instantiation (binding of types).
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/interceptors.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/interceptors.dart
index b676c1b..02235c4 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/interceptors.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/interceptors.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 library _interceptors;
 
 import 'dart:_js_embedded_names'
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/internal_patch.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/internal_patch.dart
index 77884e2..af49181 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/internal_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/internal_patch.dart
@@ -2,6 +2,8 @@
 // for details. All 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:core' hide Symbol;
 import 'dart:core' as core;
 import 'dart:_js_primitives' show printString;
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 4f3894d..8460b21 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/io_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/io_patch.dart
@@ -2,6 +2,8 @@
 // for details. All 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:_js_helper' show patch;
 import 'dart:_internal' hide Symbol;
 import 'dart:async';
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/isolate_patch.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/isolate_patch.dart
index d781e7a..9251920 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/isolate_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/isolate_patch.dart
@@ -2,6 +2,8 @@
 // for details. All 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 the dart:isolate library.
 
 import "dart:async";
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/js_array.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/js_array.dart
index ff820d4..716e85f 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/js_array.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/js_array.dart
@@ -2,6 +2,8 @@
 // for details. All 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 _interceptors;
 
 class _Growable {
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 8c167115..b8640d7 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/js_helper.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 library _js_helper;
 
 import 'dart:_js_embedded_names'
@@ -366,7 +368,7 @@
         list.add(createRuntimeType(_arguments[start + index]));
       }
     }
-    return list;
+    return JSArray.markUnmodifiableList(list);
   }
 
   List get positionalArguments {
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/js_names.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/js_names.dart
index cb4aa0e..3498028 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/js_names.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/js_names.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 library dart._js_names;
 
 import 'dart:_js_embedded_names'
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/js_number.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/js_number.dart
index 918c1ba..30d8c1d 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/js_number.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/js_number.dart
@@ -2,6 +2,8 @@
 // for details. All 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 _interceptors;
 
 /// The super interceptor class for [JSInt] and [JSDouble]. The compiler
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/js_primitives.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/js_primitives.dart
index 97577a0..5f55985 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/js_primitives.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/js_primitives.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 /// dart2js "primitives", that is, features that cannot be implemented without
 /// access to JavaScript features.
 library dart2js._js_primitives;
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/js_rti.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/js_rti.dart
index fd82931..9487c0d 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/js_rti.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/js_rti.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 /// This part contains helpers for supporting runtime type information.
 ///
 /// The helper use a mixture of Dart and JavaScript objects. To indicate which
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/js_string.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/js_string.dart
index 39370d7..4a1d1ef 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/js_string.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/js_string.dart
@@ -2,6 +2,8 @@
 // for details. All 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 _interceptors;
 
 /// The interceptor class for [String]. The compiler recognizes this
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/linked_hash_map.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/linked_hash_map.dart
index 42ad0c4..307b108 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/linked_hash_map.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/linked_hash_map.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 // Efficient JavaScript based implementation of a linked hash map used as a
 // backing map for constant maps and the [LinkedHashMap] patch
 
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/math_patch.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/math_patch.dart
index 677953e..369045e 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/math_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/math_patch.dart
@@ -2,6 +2,8 @@
 // for details. All 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, checkNum;
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart
index 6f8018a..005b14f 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart
@@ -2,6 +2,8 @@
 // for details. All 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 library for dart:mirrors.
 
 import 'dart:_js_helper' show patch;
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/native_helper.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/native_helper.dart
index ccfa26f..058352a 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/native_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/native_helper.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of _js_helper;
 
 // TODO(ngeoffray): stop using this method once our optimizers can
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/native_typed_data.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/native_typed_data.dart
index 0a91641..63c4cba 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/native_typed_data.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/native_typed_data.dart
@@ -2,6 +2,8 @@
 // for details. All 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.
 library dart.typed_data.implementation;
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/regexp_helper.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/regexp_helper.dart
index 3dacc06..4b65967 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/regexp_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/regexp_helper.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of _js_helper;
 
 // Helper method used by internal libraries.
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
index f7ca527..5ad56dc 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 /// This library contains support for runtime type information.
 library rti;
 
@@ -2147,11 +2149,16 @@
     }
   }
 
+  // TODO(fishythefish): Disallow JavaScriptFunction as a subtype of function
+  // types using features inaccessible from JavaScript.
+
   if (isGenericFunctionKind(t)) {
+    if (isJsFunctionType(s)) return true;
     return _isGenericFunctionSubtype(universe, s, sEnv, t, tEnv);
   }
 
   if (isFunctionKind(t)) {
+    if (isJsFunctionType(s)) return true;
     return _isFunctionSubtype(universe, s, sEnv, t, tEnv);
   }
 
@@ -2398,6 +2405,11 @@
     Rti._getKind(t) == Rti.kindInterface &&
     Rti._getInterfaceName(t) == JS_GET_NAME(JsGetName.FUNCTION_CLASS_TYPE_NAME);
 
+bool isJsFunctionType(Rti t) =>
+    Rti._getKind(t) == Rti.kindInterface &&
+    Rti._getInterfaceName(t) ==
+        JS_GET_NAME(JsGetName.JS_FUNCTION_CLASS_TYPE_NAME);
+
 /// Unchecked cast to Rti.
 Rti _castToRti(s) => JS('Rti', '#', s);
 
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/shared/async_await_error_codes.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/shared/async_await_error_codes.dart
index f87406b..0e9d7b2 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/shared/async_await_error_codes.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/shared/async_await_error_codes.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 /// Contains error codes that transformed async/async* functions use to
 /// communicate with js_helper functions.
 
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 50cf7e8..389c6db 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
@@ -2,6 +2,8 @@
 // for details. All 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
+
 /// Contains the names of globals that are embedded into the output by the
 /// compiler.
 ///
@@ -326,6 +328,9 @@
   /// String representation of the type of the function class.
   FUNCTION_CLASS_TYPE_NAME,
 
+  /// String representation of the type of the JavaScriptFunction class.
+  JS_FUNCTION_CLASS_TYPE_NAME,
+
   /// String recipe for the [bool] type.
   BOOL_RECIPE,
 
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 7666379..cab107f 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
@@ -2,6 +2,8 @@
 // for details. All 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
+
 /// Constants and predicates used for encoding and decoding type recipes.
 ///
 /// This library is shared between the compiler and the runtime system.
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/string_helper.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/string_helper.dart
index ea5374e..5290dc9 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/string_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/string_helper.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of _js_helper;
 
 stringIndexOfStringUnchecked(receiver, other, startIndex) {
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/typed_data_patch.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/typed_data_patch.dart
index 615c9da..20fe6f6 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/typed_data_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/typed_data_patch.dart
@@ -2,6 +2,8 @@
 // for details. All 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:_js_helper' show patch;
 import 'dart:_native_typed_data';
 
diff --git a/sdk_nnbd/lib/_internal/sdk_library_metadata/lib/libraries.dart b/sdk_nnbd/lib/_internal/sdk_library_metadata/lib/libraries.dart
index ba141fa..9d41ab3 100644
--- a/sdk_nnbd/lib/_internal/sdk_library_metadata/lib/libraries.dart
+++ b/sdk_nnbd/lib/_internal/sdk_library_metadata/lib/libraries.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 library libraries;
 
 /**
diff --git a/sdk_nnbd/lib/_internal/vm/bin/builtin.dart b/sdk_nnbd/lib/_internal/vm/bin/builtin.dart
new file mode 100644
index 0000000..69ebae3
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/bin/builtin.dart
@@ -0,0 +1,349 @@
+// 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.
+
+// @dart = 2.5
+
+library builtin;
+
+// NOTE: Do not import 'dart:io' in builtin.
+import 'dart:async';
+import 'dart:collection' hide LinkedList, LinkedListEntry;
+import 'dart:_internal' hide Symbol;
+import 'dart:isolate';
+import 'dart:typed_data';
+
+// Embedder sets this to true if the --trace-loading flag was passed on the
+// command line.
+bool _traceLoading = false;
+
+// Before handling an embedder entrypoint we finalize the setup of the
+// dart:_builtin library.
+bool _setupCompleted = false;
+
+// 'print' implementation.
+// The standalone embedder registers the closurized _print function with the
+// dart:core library.
+void _printString(String s) native "Builtin_PrintString";
+
+void _print(arg) {
+  _printString(arg.toString());
+}
+
+@pragma("vm:entry-point")
+_getPrintClosure() => _print;
+
+// Asynchronous loading of resources.
+// The embedder forwards loading requests to the service isolate.
+
+// A port for communicating with the service isolate for I/O.
+@pragma("vm:entry-point")
+SendPort _loadPort;
+
+// The isolateId used to communicate with the service isolate for I/O.
+@pragma("vm:entry-point")
+int _isolateId;
+
+// 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.
+const _Dart_kResolvePackageUri = 8; // Resolve a package: uri.
+
+// Make a request to the loader. Future will complete with result which is
+// either a Uri or a List<int>.
+Future<T> _makeLoaderRequest<T>(int tag, String uri) {
+  assert(_isolateId != null);
+  if (_loadPort == null) {
+    throw new UnsupportedError("Service isolate is not available.");
+  }
+  Completer completer = new Completer<T>();
+  RawReceivePort port = new RawReceivePort();
+  port.handler = (msg) {
+    // Close the port.
+    port.close();
+    completer.complete(msg);
+  };
+  _loadPort.send([_traceLoading, _isolateId, tag, port.sendPort, uri]);
+  return completer.future;
+}
+
+// The current working directory when the embedder was launched.
+Uri _workingDirectory;
+// The URI that the root script was loaded from. Remembered so that
+// package imports can be resolved relative to it. The root script is the basis
+// for the root library in the VM.
+Uri _rootScript;
+// The package root set on the command line.
+Uri _packageRoot;
+
+// Special handling for Windows paths so that they are compatible with URI
+// handling.
+// Embedder sets this to true if we are running on Windows.
+@pragma("vm:entry-point")
+bool _isWindows = false;
+
+// Logging from builtin.dart is prefixed with a '*'.
+String _logId = (Isolate.current.hashCode % 0x100000).toRadixString(16);
+_log(msg) {
+  _print("* $_logId $msg");
+}
+
+_sanitizeWindowsPath(path) {
+  // For Windows we need to massage the paths a bit according to
+  // http://blogs.msdn.com/b/ie/archive/2006/12/06/file-uris-in-windows.aspx
+  //
+  // Convert
+  // C:\one\two\three
+  // to
+  // /C:/one/two/three
+
+  if (_isWindows == false) {
+    // Do nothing when not running Windows.
+    return path;
+  }
+
+  var fixedPath = "${path.replaceAll('\\', '/')}";
+
+  if ((path.length > 2) && (path[1] == ':')) {
+    // Path begins with a drive letter.
+    return '/$fixedPath';
+  }
+
+  return fixedPath;
+}
+
+_trimWindowsPath(path) {
+  // Convert /X:/ to X:/.
+  if (_isWindows == false) {
+    // Do nothing when not running Windows.
+    return path;
+  }
+  if (!path.startsWith('/') || (path.length < 3)) {
+    return path;
+  }
+  // Match '/?:'.
+  if ((path[0] == '/') && (path[2] == ':')) {
+    // Remove leading '/'.
+    return path.substring(1);
+  }
+  return path;
+}
+
+// Ensure we have a trailing slash character.
+_enforceTrailingSlash(uri) {
+  if (!uri.endsWith('/')) {
+    return '$uri/';
+  }
+  return uri;
+}
+
+// Embedder Entrypoint:
+// The embedder calls this method with the current working directory.
+@pragma("vm:entry-point")
+void _setWorkingDirectory(String cwd) {
+  if (!_setupCompleted) {
+    _setupHooks();
+  }
+  if (_traceLoading) {
+    _log('Setting working directory: $cwd');
+  }
+  _workingDirectory = new Uri.directory(cwd);
+  if (_traceLoading) {
+    _log('Working directory URI: $_workingDirectory');
+  }
+}
+
+// Embedder Entrypoint:
+// The embedder calls this method with a custom package root.
+@pragma("vm:entry-point")
+String _setPackageRoot(String packageRoot) {
+  if (!_setupCompleted) {
+    _setupHooks();
+  }
+  if (_traceLoading) {
+    _log('Setting package root: $packageRoot');
+  }
+  if (packageRoot.startsWith('file:') ||
+      packageRoot.startsWith('http:') ||
+      packageRoot.startsWith('https:')) {
+    packageRoot = _enforceTrailingSlash(packageRoot);
+    _packageRoot = _workingDirectory.resolve(packageRoot);
+  } else {
+    packageRoot = _sanitizeWindowsPath(packageRoot);
+    packageRoot = _trimWindowsPath(packageRoot);
+    _packageRoot = _workingDirectory.resolveUri(new Uri.directory(packageRoot));
+  }
+  // Now that we have determined the packageRoot value being used, set it
+  // up for use in Platform.packageRoot. This is only set when the embedder
+  // sets up the package root. Automatically discovered package root will
+  // not update the VMLibraryHooks value.
+  var packageRootStr = _packageRoot.toString();
+  VMLibraryHooks.packageRootString = packageRootStr;
+  if (_traceLoading) {
+    _log('Package root URI: $_packageRoot');
+  }
+  return packageRootStr;
+}
+
+// Embedder Entrypoint:
+@pragma("vm:entry-point")
+String _setPackagesMap(String packagesParam) {
+  if (!_setupCompleted) {
+    _setupHooks();
+  }
+  // First convert the packages parameter from the command line to a URI which
+  // can be handled by the loader code.
+  // TODO(iposva): Consider refactoring the common code below which is almost
+  // shared with resolution of the root script.
+  if (_traceLoading) {
+    _log("Resolving packages map: $packagesParam");
+  }
+  if (_workingDirectory == null) {
+    throw 'No current working directory set.';
+  }
+  var packagesName = _sanitizeWindowsPath(packagesParam);
+  var packagesUri = Uri.parse(packagesName);
+  if (packagesUri.scheme == '') {
+    // Script does not have a scheme, assume that it is a path,
+    // resolve it against the working directory.
+    packagesUri = _workingDirectory.resolveUri(packagesUri);
+  }
+  var packagesUriStr = packagesUri.toString();
+  VMLibraryHooks.packageConfigString = packagesUriStr;
+  if (_traceLoading) {
+    _log('Resolved packages map to: $packagesUri');
+  }
+  return packagesUriStr;
+}
+
+// Resolves the script uri in the current working directory iff the given uri
+// did not specify a scheme (e.g. a path to a script file on the command line).
+@pragma("vm:entry-point")
+String _resolveScriptUri(String scriptName) {
+  if (_traceLoading) {
+    _log("Resolving script: $scriptName");
+  }
+  if (_workingDirectory == null) {
+    throw 'No current working directory set.';
+  }
+  scriptName = _sanitizeWindowsPath(scriptName);
+
+  var scriptUri = Uri.parse(scriptName);
+  if (scriptUri.scheme == '') {
+    // Script does not have a scheme, assume that it is a path,
+    // resolve it against the working directory.
+    scriptUri = _workingDirectory.resolveUri(scriptUri);
+  }
+
+  // Remember the root script URI so that we can resolve packages based on
+  // this location.
+  _rootScript = scriptUri;
+
+  if (_traceLoading) {
+    _log('Resolved entry point to: $_rootScript');
+  }
+  return scriptUri.toString();
+}
+
+// Only used by vm/cc unit tests.
+Uri _resolvePackageUri(Uri uri) {
+  assert(_packageRoot != null);
+  return _packageRoot.resolve(uri.path);
+}
+
+// Returns either a file path or a URI starting with http[s]:, as a String.
+String _filePathFromUri(String userUri) {
+  var uri = Uri.parse(userUri);
+  if (_traceLoading) {
+    _log('Getting file path from: $uri');
+  }
+
+  var path;
+  switch (uri.scheme) {
+    case '':
+    case 'file':
+      return uri.toFilePath();
+    case 'package':
+      return _filePathFromUri(_resolvePackageUri(uri).toString());
+    case 'data':
+    case 'http':
+    case 'https':
+      return uri.toString();
+    default:
+      // Only handling file, http, and package URIs
+      // in standalone binary.
+      if (_traceLoading) {
+        _log('Unknown scheme (${uri.scheme}) in $uri.');
+      }
+      throw 'Not a known scheme: $uri';
+  }
+}
+
+// Register callbacks and hooks with the rest of the core libraries.
+@pragma("vm:entry-point")
+_setupHooks() {
+  _setupCompleted = true;
+  VMLibraryHooks.resourceReadAsBytes = _resourceReadAsBytes;
+
+  VMLibraryHooks.packageRootUriFuture = _getPackageRootFuture;
+  VMLibraryHooks.packageConfigUriFuture = _getPackageConfigFuture;
+  VMLibraryHooks.resolvePackageUriFuture = _resolvePackageUriFuture;
+}
+
+// Handling of Resource class by dispatching to the load port.
+Future<List<int>> _resourceReadAsBytes(Uri uri) async {
+  List response =
+      await _makeLoaderRequest<List<int>>(_Dart_kResourceLoad, uri.toString());
+  if (response[4] is String) {
+    // Throw the error.
+    throw response[4];
+  } else {
+    return response[4];
+  }
+}
+
+// TODO(mfairhurst): remove this
+Future<Uri> _getPackageRootFuture() {
+  if (_traceLoading) {
+    _log("Request for package root from user code.");
+  }
+  // Return null, as the `packages/` directory is not supported in dart 2.
+  return new Future.value(null);
+}
+
+Future<Uri> _getPackageConfigFuture() {
+  if (_traceLoading) {
+    _log("Request for package config from user code.");
+  }
+  assert(_loadPort != null);
+  return _makeLoaderRequest<Uri>(_Dart_kGetPackageConfigUri, null);
+}
+
+Future<Uri> _resolvePackageUriFuture(Uri packageUri) async {
+  if (_traceLoading) {
+    _log("Request for package Uri resolution from user code: $packageUri");
+  }
+  if (packageUri.scheme != "package") {
+    if (_traceLoading) {
+      _log("Non-package Uri, returning unmodified: $packageUri");
+    }
+    // Return the incoming parameter if not passed a package: URI.
+    return packageUri;
+  }
+  var result = await _makeLoaderRequest<Uri>(
+      _Dart_kResolvePackageUri, packageUri.toString());
+  if (result is! Uri) {
+    if (_traceLoading) {
+      _log("Exception when resolving package URI: $packageUri");
+    }
+    result = null;
+  }
+  if (_traceLoading) {
+    _log("Resolved '$packageUri' to '$result'");
+  }
+  return result;
+}
diff --git a/sdk_nnbd/lib/_internal/vm/bin/cli_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/cli_patch.dart
new file mode 100644
index 0000000..6e373a5
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/bin/cli_patch.dart
@@ -0,0 +1,10 @@
+// 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.
+
+// @dart = 2.5
+
+import "dart:_internal" show patch;
+
+@patch
+void _waitForEvent(int timeoutMillis) native "CLI_WaitForEvent";
diff --git a/sdk_nnbd/lib/_internal/vm/bin/common_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/common_patch.dart
new file mode 100644
index 0000000..f974bae
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/bin/common_patch.dart
@@ -0,0 +1,64 @@
+// 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.
+
+// @dart = 2.5
+
+/// Note: the VM concatenates all patch files into a single patch file. This
+/// file is the first patch in "dart:io" which contains all the imports used by
+/// patches of that library. We plan to change this when we have a shared front
+/// end and simply use parts.
+
+import "dart:_internal" show VMLibraryHooks, patch;
+
+import "dart:async"
+    show
+        Completer,
+        Future,
+        Stream,
+        StreamConsumer,
+        StreamController,
+        StreamSubscription,
+        Timer,
+        Zone,
+        scheduleMicrotask;
+
+import "dart:collection" show HashMap;
+
+import "dart:convert" show Encoding, utf8;
+
+import "dart:developer" show registerExtension;
+
+import "dart:isolate" show RawReceivePort, ReceivePort, SendPort;
+
+import "dart:math" show min;
+
+import "dart:nativewrappers" show NativeFieldWrapperClass1;
+
+import "dart:typed_data" show Uint8List;
+
+/// These are the additional parts of this patch library:
+// part "directory_patch.dart";
+// part "eventhandler_patch.dart";
+// part "file_patch.dart";
+// part "file_system_entity_patch.dart";
+// part "filter_patch.dart";
+// part "io_service_patch.dart";
+// part "platform_patch.dart";
+// part "process_patch.dart";
+// part "socket_patch.dart";
+// part "stdio_patch.dart";
+// part "secure_socket_patch.dart";
+// part "sync_socket_patch.dart";
+
+@patch
+class _IOCrypto {
+  @patch
+  static Uint8List getRandomBytes(int count) native "Crypto_GetRandomBytes";
+}
+
+@pragma("vm:entry-point", "call")
+_setupHooks() {
+  VMLibraryHooks.eventHandlerSendData = _EventHandler._sendData;
+  VMLibraryHooks.timerMillisecondClock = _EventHandler._timerMillisecondClock;
+}
diff --git a/sdk_nnbd/lib/_internal/vm/bin/directory_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/directory_patch.dart
new file mode 100644
index 0000000..951bd09
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/bin/directory_patch.dart
@@ -0,0 +1,73 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "common_patch.dart";
+
+@patch
+class _Directory {
+  @patch
+  static _current(_Namespace namespace) native "Directory_Current";
+  @patch
+  static _setCurrent(_Namespace namespace, Uint8List rawPath)
+      native "Directory_SetCurrent";
+  @patch
+  static _createTemp(_Namespace namespace, Uint8List rawPath)
+      native "Directory_CreateTemp";
+  @patch
+  static String _systemTemp(_Namespace namespace) native "Directory_SystemTemp";
+  @patch
+  static _exists(_Namespace namespace, Uint8List rawPath)
+      native "Directory_Exists";
+  @patch
+  static _create(_Namespace namespace, Uint8List rawPath)
+      native "Directory_Create";
+  @patch
+  static _deleteNative(_Namespace namespace, Uint8List rawPath, bool recursive)
+      native "Directory_Delete";
+  @patch
+  static _rename(_Namespace namespace, Uint8List rawPath, String newPath)
+      native "Directory_Rename";
+  @patch
+  static void _fillWithDirectoryListing(
+      _Namespace namespace,
+      List<FileSystemEntity> list,
+      Uint8List rawPath,
+      bool recursive,
+      bool followLinks) native "Directory_FillWithDirectoryListing";
+}
+
+@patch
+class _AsyncDirectoryListerOps {
+  @patch
+  factory _AsyncDirectoryListerOps(int pointer) =>
+      new _AsyncDirectoryListerOpsImpl(pointer);
+}
+
+class _AsyncDirectoryListerOpsImpl extends NativeFieldWrapperClass1
+    implements _AsyncDirectoryListerOps {
+  _AsyncDirectoryListerOpsImpl._();
+
+  factory _AsyncDirectoryListerOpsImpl(int pointer) =>
+      new _AsyncDirectoryListerOpsImpl._().._setPointer(pointer);
+
+  void _setPointer(int pointer)
+      native "Directory_SetAsyncDirectoryListerPointer";
+  int getPointer() native "Directory_GetAsyncDirectoryListerPointer";
+}
+
+// Corelib 'Uri.base' implementation.
+// Uri.base is susceptible to changes in the current working directory.
+Uri _uriBaseClosure() {
+  var result = _Directory._current(_Namespace._namespace);
+  if (result is OSError) {
+    throw new FileSystemException(
+        "Getting current working directory failed", "", result);
+  }
+  return new Uri.directory(result);
+}
+
+@pragma("vm:entry-point", "call")
+_getUriBaseClosure() => _uriBaseClosure;
diff --git a/sdk_nnbd/lib/_internal/vm/bin/eventhandler_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/eventhandler_patch.dart
new file mode 100644
index 0000000..abc5e21
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/bin/eventhandler_patch.dart
@@ -0,0 +1,17 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "common_patch.dart";
+
+@patch
+class _EventHandler {
+  @patch
+  static void _sendData(Object sender, SendPort sendPort, int data)
+      native "EventHandler_SendData";
+
+  static int _timerMillisecondClock()
+      native "EventHandler_TimerMillisecondClock";
+}
diff --git a/sdk_nnbd/lib/_internal/vm/bin/file_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/file_patch.dart
new file mode 100644
index 0000000..3ebdc82
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/bin/file_patch.dart
@@ -0,0 +1,423 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "common_patch.dart";
+
+@patch
+class _File {
+  @patch
+  static _exists(_Namespace namespace, Uint8List rawPath) native "File_Exists";
+  @patch
+  static _create(_Namespace namespace, Uint8List rawPath) native "File_Create";
+  @patch
+  static _createLink(_Namespace namespace, Uint8List rawPath, String target)
+      native "File_CreateLink";
+  @patch
+  static _linkTarget(_Namespace namespace, Uint8List rawPath)
+      native "File_LinkTarget";
+  @patch
+  static _deleteNative(_Namespace namespace, Uint8List rawPath)
+      native "File_Delete";
+  @patch
+  static _deleteLinkNative(_Namespace namespace, Uint8List rawPath)
+      native "File_DeleteLink";
+  @patch
+  static _rename(_Namespace namespace, Uint8List oldPath, String newPath)
+      native "File_Rename";
+  @patch
+  static _renameLink(_Namespace namespace, Uint8List oldPath, String newPath)
+      native "File_RenameLink";
+  @patch
+  static _copy(_Namespace namespace, Uint8List oldPath, String newPath)
+      native "File_Copy";
+  @patch
+  static _lengthFromPath(_Namespace namespace, Uint8List rawPath)
+      native "File_LengthFromPath";
+  @patch
+  static _lastModified(_Namespace namespace, Uint8List rawPath)
+      native "File_LastModified";
+  @patch
+  static _setLastModified(_Namespace namespace, Uint8List rawPath, int millis)
+      native "File_SetLastModified";
+  @patch
+  static _lastAccessed(_Namespace namespace, Uint8List rawPath)
+      native "File_LastAccessed";
+  @patch
+  static _setLastAccessed(_Namespace namespace, Uint8List rawPath, int millis)
+      native "File_SetLastAccessed";
+  @patch
+  static _open(_Namespace namespace, Uint8List rawPath, int mode)
+      native "File_Open";
+  @patch
+  static int _openStdio(int fd) native "File_OpenStdio";
+}
+
+@patch
+class _RandomAccessFileOps {
+  @patch
+  factory _RandomAccessFileOps(int pointer) =>
+      new _RandomAccessFileOpsImpl(pointer);
+}
+
+@pragma("vm:entry-point")
+class _RandomAccessFileOpsImpl extends NativeFieldWrapperClass1
+    implements _RandomAccessFileOps {
+  _RandomAccessFileOpsImpl._();
+
+  factory _RandomAccessFileOpsImpl(int pointer) =>
+      new _RandomAccessFileOpsImpl._().._setPointer(pointer);
+
+  void _setPointer(int pointer) native "File_SetPointer";
+
+  int getPointer() native "File_GetPointer";
+  int close() native "File_Close";
+  readByte() native "File_ReadByte";
+  read(int bytes) native "File_Read";
+  readInto(List<int> buffer, int start, int end) native "File_ReadInto";
+  writeByte(int value) native "File_WriteByte";
+  writeFrom(List<int> buffer, int start, int end) native "File_WriteFrom";
+  position() native "File_Position";
+  setPosition(int position) native "File_SetPosition";
+  truncate(int length) native "File_Truncate";
+  length() native "File_Length";
+  flush() native "File_Flush";
+  lock(int lock, int start, int end) native "File_Lock";
+}
+
+class _WatcherPath {
+  final int pathId;
+  final String path;
+  final int events;
+  int count = 0;
+  _WatcherPath(this.pathId, this.path, this.events);
+}
+
+@patch
+class _FileSystemWatcher {
+  void _pathWatchedEnd();
+
+  static int _id;
+  static final Map<int, _WatcherPath> _idMap = {};
+
+  final String _path;
+  final int _events;
+  final bool _recursive;
+
+  _WatcherPath _watcherPath;
+
+  StreamController<FileSystemEvent> _broadcastController;
+
+  @patch
+  static Stream<FileSystemEvent> _watch(
+      String path, int events, bool recursive) {
+    if (Platform.isLinux) {
+      return new _InotifyFileSystemWatcher(path, events, recursive)._stream;
+    }
+    if (Platform.isWindows) {
+      return new _Win32FileSystemWatcher(path, events, recursive)._stream;
+    }
+    if (Platform.isMacOS) {
+      return new _FSEventStreamFileSystemWatcher(path, events, recursive)
+          ._stream;
+    }
+    throw new FileSystemException(
+        "File system watching is not supported on this platform");
+  }
+
+  _FileSystemWatcher._(this._path, this._events, this._recursive) {
+    if (!isSupported) {
+      throw new FileSystemException(
+          "File system watching is not supported on this platform", _path);
+    }
+    _broadcastController = new StreamController<FileSystemEvent>.broadcast(
+        onListen: _listen, onCancel: _cancel);
+  }
+
+  Stream<FileSystemEvent> get _stream => _broadcastController.stream;
+
+  void _listen() {
+    if (_id == null) {
+      try {
+        _id = _initWatcher();
+        _newWatcher();
+      } catch (e) {
+        _broadcastController.addError(new FileSystemException(
+            "Failed to initialize file system entity watcher", null, e));
+        _broadcastController.close();
+        return;
+      }
+    }
+    var pathId;
+    try {
+      pathId =
+          _watchPath(_id, _Namespace._namespace, _path, _events, _recursive);
+    } catch (e) {
+      _broadcastController
+          .addError(new FileSystemException("Failed to watch path", _path, e));
+      _broadcastController.close();
+      return;
+    }
+    if (!_idMap.containsKey(pathId)) {
+      _idMap[pathId] = new _WatcherPath(pathId, _path, _events);
+    }
+    _watcherPath = _idMap[pathId];
+    _watcherPath.count++;
+    _pathWatched().pipe(_broadcastController);
+  }
+
+  void _cancel() {
+    if (_watcherPath != null) {
+      assert(_watcherPath.count > 0);
+      _watcherPath.count--;
+      if (_watcherPath.count == 0) {
+        _unwatchPath(_id, _watcherPath.pathId);
+        _pathWatchedEnd();
+        _idMap.remove(_watcherPath.pathId);
+      }
+      _watcherPath = null;
+    }
+    if (_idMap.isEmpty && _id != null) {
+      _closeWatcher(_id);
+      _doneWatcher();
+      _id = null;
+    }
+  }
+
+  // Called when (and after) a new watcher instance is created and available.
+  void _newWatcher() {}
+  // Called when a watcher is no longer needed.
+  void _doneWatcher() {}
+  // Called when a new path is being watched.
+  Stream _pathWatched() {}
+  // Called when a path is no longer being watched.
+  void _donePathWatched() {}
+
+  static _WatcherPath _pathFromPathId(int pathId) {
+    return _idMap[pathId];
+  }
+
+  static Stream _listenOnSocket(int socketId, int id, int pathId) {
+    var native = new _NativeSocket.watch(socketId);
+    var socket = new _RawSocket(native);
+    return socket.expand((event) {
+      var stops = [];
+      var events = [];
+      var pair = {};
+      if (event == RawSocketEvent.read) {
+        String getPath(event) {
+          var path = _pathFromPathId(event[4]).path;
+          if (event[2] != null && event[2].isNotEmpty) {
+            path += Platform.pathSeparator;
+            path += event[2];
+          }
+          return path;
+        }
+
+        bool getIsDir(event) {
+          if (Platform.isWindows) {
+            // Windows does not get 'isDir' as part of the event.
+            return FileSystemEntity.isDirectorySync(getPath(event));
+          }
+          return (event[0] & FileSystemEvent._isDir) != 0;
+        }
+
+        void add(id, event) {
+          if ((event.type & _pathFromPathId(id).events) == 0) return;
+          events.add([id, event]);
+        }
+
+        void rewriteMove(event, isDir) {
+          if (event[3]) {
+            add(event[4], new FileSystemCreateEvent._(getPath(event), isDir));
+          } else {
+            add(event[4], new FileSystemDeleteEvent._(getPath(event), isDir));
+          }
+        }
+
+        int eventCount;
+        do {
+          eventCount = 0;
+          for (var event in _readEvents(id, pathId)) {
+            if (event == null) continue;
+            eventCount++;
+            int pathId = event[4];
+            if (!_idMap.containsKey(pathId)) {
+              // Path is no longer being wathed.
+              continue;
+            }
+            bool isDir = getIsDir(event);
+            var path = getPath(event);
+            if ((event[0] & FileSystemEvent.create) != 0) {
+              add(event[4], new FileSystemCreateEvent._(path, isDir));
+            }
+            if ((event[0] & FileSystemEvent.modify) != 0) {
+              add(event[4], new FileSystemModifyEvent._(path, isDir, true));
+            }
+            if ((event[0] & FileSystemEvent._modifyAttributes) != 0) {
+              add(event[4], new FileSystemModifyEvent._(path, isDir, false));
+            }
+            if ((event[0] & FileSystemEvent.move) != 0) {
+              int link = event[1];
+              if (link > 0) {
+                pair.putIfAbsent(pathId, () => {});
+                if (pair[pathId].containsKey(link)) {
+                  add(
+                      event[4],
+                      new FileSystemMoveEvent._(
+                          getPath(pair[pathId][link]), isDir, path));
+                  pair[pathId].remove(link);
+                } else {
+                  pair[pathId][link] = event;
+                }
+              } else {
+                rewriteMove(event, isDir);
+              }
+            }
+            if ((event[0] & FileSystemEvent.delete) != 0) {
+              add(event[4], new FileSystemDeleteEvent._(path, isDir));
+            }
+            if ((event[0] & FileSystemEvent._deleteSelf) != 0) {
+              add(event[4], new FileSystemDeleteEvent._(path, isDir));
+              // Signal done event.
+              stops.add([event[4], null]);
+            }
+          }
+        } while (eventCount > 0);
+        // Be sure to clear this manually, as the sockets are not read through
+        // the _NativeSocket interface.
+        native.available = 0;
+        for (var map in pair.values) {
+          for (var event in map.values) {
+            rewriteMove(event, getIsDir(event));
+          }
+        }
+      } else if (event == RawSocketEvent.closed) {
+      } else if (event == RawSocketEvent.readClosed) {
+      } else {
+        assert(false);
+      }
+      events.addAll(stops);
+      return events;
+    });
+  }
+
+  @patch
+  static bool get isSupported native "FileSystemWatcher_IsSupported";
+
+  static int _initWatcher() native "FileSystemWatcher_InitWatcher";
+  static void _closeWatcher(int id) native "FileSystemWatcher_CloseWatcher";
+
+  static int _watchPath(int id, _Namespace namespace, String path, int events,
+      bool recursive) native "FileSystemWatcher_WatchPath";
+  static void _unwatchPath(int id, int path_id)
+      native "FileSystemWatcher_UnwatchPath";
+  static List _readEvents(int id, int path_id)
+      native "FileSystemWatcher_ReadEvents";
+  static int _getSocketId(int id, int path_id)
+      native "FileSystemWatcher_GetSocketId";
+}
+
+class _InotifyFileSystemWatcher extends _FileSystemWatcher {
+  static final Map<int, StreamController> _idMap = {};
+  static StreamSubscription _subscription;
+
+  _InotifyFileSystemWatcher(path, events, recursive)
+      : super._(path, events, recursive);
+
+  void _newWatcher() {
+    int id = _FileSystemWatcher._id;
+    _subscription =
+        _FileSystemWatcher._listenOnSocket(id, id, 0).listen((event) {
+      if (_idMap.containsKey(event[0])) {
+        if (event[1] != null) {
+          _idMap[event[0]].add(event[1]);
+        } else {
+          _idMap[event[0]].close();
+        }
+      }
+    });
+  }
+
+  void _doneWatcher() {
+    _subscription.cancel();
+  }
+
+  Stream _pathWatched() {
+    var pathId = _watcherPath.pathId;
+    if (!_idMap.containsKey(pathId)) {
+      _idMap[pathId] = new StreamController<FileSystemEvent>.broadcast();
+    }
+    return _idMap[pathId].stream;
+  }
+
+  void _pathWatchedEnd() {
+    var pathId = _watcherPath.pathId;
+    if (!_idMap.containsKey(pathId)) return;
+    _idMap[pathId].close();
+    _idMap.remove(pathId);
+  }
+}
+
+class _Win32FileSystemWatcher extends _FileSystemWatcher {
+  StreamSubscription _subscription;
+  StreamController _controller;
+
+  _Win32FileSystemWatcher(path, events, recursive)
+      : super._(path, events, recursive);
+
+  Stream _pathWatched() {
+    var pathId = _watcherPath.pathId;
+    _controller = new StreamController<FileSystemEvent>();
+    _subscription =
+        _FileSystemWatcher._listenOnSocket(pathId, 0, pathId).listen((event) {
+      assert(event[0] == pathId);
+      if (event[1] != null) {
+        _controller.add(event[1]);
+      } else {
+        _controller.close();
+      }
+    });
+    return _controller.stream;
+  }
+
+  void _pathWatchedEnd() {
+    _subscription.cancel();
+    _controller.close();
+  }
+}
+
+class _FSEventStreamFileSystemWatcher extends _FileSystemWatcher {
+  StreamSubscription _subscription;
+  StreamController _controller;
+
+  _FSEventStreamFileSystemWatcher(path, events, recursive)
+      : super._(path, events, recursive);
+
+  Stream _pathWatched() {
+    var pathId = _watcherPath.pathId;
+    var socketId = _FileSystemWatcher._getSocketId(0, pathId);
+    _controller = new StreamController<FileSystemEvent>();
+    _subscription =
+        _FileSystemWatcher._listenOnSocket(socketId, 0, pathId).listen((event) {
+      if (event[1] != null) {
+        _controller.add(event[1]);
+      } else {
+        _controller.close();
+      }
+    });
+    return _controller.stream;
+  }
+
+  void _pathWatchedEnd() {
+    _subscription.cancel();
+    _controller.close();
+  }
+}
+
+@pragma("vm:entry-point", "call")
+Uint8List _makeUint8ListView(Uint8List source, int offsetInBytes, int length) {
+  return new Uint8List.view(source.buffer, offsetInBytes, length);
+}
diff --git a/sdk_nnbd/lib/_internal/vm/bin/file_system_entity_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/file_system_entity_patch.dart
new file mode 100644
index 0000000..841219e
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/bin/file_system_entity_patch.dart
@@ -0,0 +1,26 @@
+// 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 "common_patch.dart";
+
+@patch
+class FileStat {
+  @patch
+  static _statSync(_Namespace namespace, String path) native "File_Stat";
+}
+
+@patch
+class FileSystemEntity {
+  @patch
+  static _getTypeNative(_Namespace namespace, Uint8List rawPath,
+      bool followLinks) native "File_GetType";
+  @patch
+  static _identicalNative(_Namespace namespace, String path1, String path2)
+      native "File_AreIdentical";
+  @patch
+  static _resolveSymbolicLinks(_Namespace namespace, Uint8List path)
+      native "File_ResolveSymbolicLinks";
+}
diff --git a/sdk_nnbd/lib/_internal/vm/bin/filter_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/filter_patch.dart
new file mode 100644
index 0000000..a31f838
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/bin/filter_patch.dart
@@ -0,0 +1,50 @@
+// 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 "common_patch.dart";
+
+class _FilterImpl extends NativeFieldWrapperClass1 implements RawZLibFilter {
+  void process(List<int> data, int start, int end) native "Filter_Process";
+
+  List<int> processed({bool flush: true, bool end: false})
+      native "Filter_Processed";
+}
+
+class _ZLibInflateFilter extends _FilterImpl {
+  _ZLibInflateFilter(int windowBits, List<int> dictionary, bool raw) {
+    _init(windowBits, dictionary, raw);
+  }
+  void _init(int windowBits, List<int> dictionary, bool raw)
+      native "Filter_CreateZLibInflate";
+}
+
+class _ZLibDeflateFilter extends _FilterImpl {
+  _ZLibDeflateFilter(bool gzip, int level, int windowBits, int memLevel,
+      int strategy, List<int> dictionary, bool raw) {
+    _init(gzip, level, windowBits, memLevel, strategy, dictionary, raw);
+  }
+  void _init(bool gzip, int level, int windowBits, int memLevel, int strategy,
+      List<int> dictionary, bool raw) native "Filter_CreateZLibDeflate";
+}
+
+@patch
+class RawZLibFilter {
+  @patch
+  static RawZLibFilter _makeZLibDeflateFilter(
+          bool gzip,
+          int level,
+          int windowBits,
+          int memLevel,
+          int strategy,
+          List<int> dictionary,
+          bool raw) =>
+      new _ZLibDeflateFilter(
+          gzip, level, windowBits, memLevel, strategy, dictionary, raw);
+  @patch
+  static RawZLibFilter _makeZLibInflateFilter(
+          int windowBits, List<int> dictionary, bool raw) =>
+      new _ZLibInflateFilter(windowBits, dictionary, raw);
+}
diff --git a/sdk_nnbd/lib/_internal/vm/bin/io_service_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/io_service_patch.dart
new file mode 100644
index 0000000..be823a4
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/bin/io_service_patch.dart
@@ -0,0 +1,102 @@
+// 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 "common_patch.dart";
+
+class _IOServicePorts {
+  // We limit the number of IO Service ports per isolate so that we don't
+  // spawn too many threads all at once, which can crash the VM on Windows.
+  static const int maxPorts = 32;
+  List<SendPort> _ports = <SendPort>[];
+  List<SendPort> _freePorts = <SendPort>[];
+  Map<int, SendPort> _usedPorts = new HashMap<int, SendPort>();
+
+  _IOServicePorts();
+
+  SendPort _getPort(int forRequestId) {
+    if (_freePorts.isEmpty && _usedPorts.length < maxPorts) {
+      final SendPort port = _newServicePort();
+      _ports.add(port);
+      _freePorts.add(port);
+    }
+    if (!_freePorts.isEmpty) {
+      final SendPort port = _freePorts.removeLast();
+      assert(!_usedPorts.containsKey(forRequestId));
+      _usedPorts[forRequestId] = port;
+      return port;
+    }
+    // We have already allocated the max number of ports. Re-use an
+    // existing one.
+    final SendPort port = _ports[forRequestId % maxPorts];
+    _usedPorts[forRequestId] = port;
+    return port;
+  }
+
+  void _returnPort(int forRequestId) {
+    final SendPort port = _usedPorts.remove(forRequestId);
+    if (!_usedPorts.values.contains(port)) {
+      _freePorts.add(port);
+    }
+  }
+
+  static SendPort _newServicePort() native "IOService_NewServicePort";
+}
+
+@patch
+class _IOService {
+  static _IOServicePorts _servicePorts = new _IOServicePorts();
+  static RawReceivePort _receivePort;
+  static SendPort _replyToPort;
+  static HashMap<int, Completer> _messageMap = new HashMap<int, Completer>();
+  static int _id = 0;
+
+  @patch
+  static Future _dispatch(int request, List data) {
+    int id;
+    do {
+      id = _getNextId();
+    } while (_messageMap.containsKey(id));
+    final SendPort servicePort = _servicePorts._getPort(id);
+    _ensureInitialize();
+    final Completer completer = new Completer();
+    _messageMap[id] = completer;
+    try {
+      servicePort.send([id, _replyToPort, request, data]);
+    } catch (error) {
+      _messageMap.remove(id).complete(error);
+      if (_messageMap.length == 0) {
+        _finalize();
+      }
+    }
+    return completer.future;
+  }
+
+  static void _ensureInitialize() {
+    if (_receivePort == null) {
+      _receivePort = new RawReceivePort();
+      _replyToPort = _receivePort.sendPort;
+      _receivePort.handler = (data) {
+        assert(data is List && data.length == 2);
+        _messageMap.remove(data[0]).complete(data[1]);
+        _servicePorts._returnPort(data[0]);
+        if (_messageMap.length == 0) {
+          _finalize();
+        }
+      };
+    }
+  }
+
+  static void _finalize() {
+    _id = 0;
+    _receivePort.close();
+    _receivePort = null;
+  }
+
+  static int _getNextId() {
+    if (_id == 0x7FFFFFFF) _id = 0;
+    return _id++;
+  }
+}
diff --git a/sdk_nnbd/lib/_internal/vm/bin/namespace_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/namespace_patch.dart
new file mode 100644
index 0000000..bc8e2df
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/bin/namespace_patch.dart
@@ -0,0 +1,50 @@
+// 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.
+
+// @dart = 2.5
+
+@pragma("vm:entry-point")
+class _NamespaceImpl extends NativeFieldWrapperClass1 implements _Namespace {
+  _NamespaceImpl._();
+
+  static _NamespaceImpl _create(_NamespaceImpl namespace, var n)
+      native "Namespace_Create";
+  static int _getPointer(_NamespaceImpl namespace)
+      native "Namespace_GetPointer";
+  static int _getDefault() native "Namespace_GetDefault";
+
+  // If the platform supports "namespaces", this method is called by the
+  // embedder with the platform-specific namespace information.
+  static _NamespaceImpl _cachedNamespace = null;
+  static void _setupNamespace(var namespace) {
+    _cachedNamespace = _create(new _NamespaceImpl._(), namespace);
+  }
+
+  static _NamespaceImpl get _namespace {
+    if (_cachedNamespace == null) {
+      // The embedder has not supplied a namespace before one is needed, so
+      // instead use a safe-ish default value.
+      _cachedNamespace = _create(new _NamespaceImpl._(), _getDefault());
+    }
+    return _cachedNamespace;
+  }
+
+  static int get _namespacePointer => _getPointer(_namespace);
+}
+
+@patch
+@pragma("vm:entry-point")
+class _Namespace {
+  @patch
+  @pragma("vm:entry-point", "call")
+  static void _setupNamespace(var namespace) {
+    _NamespaceImpl._setupNamespace(namespace);
+  }
+
+  @patch
+  static _Namespace get _namespace => _NamespaceImpl._namespace;
+
+  @patch
+  static int get _namespacePointer => _NamespaceImpl._namespacePointer;
+}
diff --git a/sdk_nnbd/lib/_internal/vm/bin/platform_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/platform_patch.dart
new file mode 100644
index 0000000..88c10bd
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/bin/platform_patch.dart
@@ -0,0 +1,61 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "common_patch.dart";
+
+@patch
+@pragma("vm:entry-point")
+class _Platform {
+  @patch
+  static int _numberOfProcessors() native "Platform_NumberOfProcessors";
+  @patch
+  static String _pathSeparator() native "Platform_PathSeparator";
+  @patch
+  static String _operatingSystem() native "Platform_OperatingSystem";
+  @patch
+  static _operatingSystemVersion() native "Platform_OperatingSystemVersion";
+  @patch
+  static _localHostname() native "Platform_LocalHostname";
+  @patch
+  static _executable() native "Platform_ExecutableName";
+  @patch
+  static _resolvedExecutable() native "Platform_ResolvedExecutableName";
+  @patch
+  static _environment() native "Platform_Environment";
+  @patch
+  static List<String> _executableArguments()
+      native "Platform_ExecutableArguments";
+  @patch
+  static String _version() native "Platform_GetVersion";
+
+  @patch
+  static String _localeName() native "Platform_LocaleName";
+
+  @patch
+  static String _packageRoot() => VMLibraryHooks.packageRootString;
+  @patch
+  static String _packageConfig() => VMLibraryHooks.packageConfigString;
+
+  @patch
+  static Uri _script() => VMLibraryHooks.platformScript;
+
+  // This script singleton is written to by the embedder if applicable.
+  @pragma("vm:entry-point")
+  static void set _nativeScript(String path) {
+    VMLibraryHooks.platformScript = (() {
+      if (path.startsWith('http:') ||
+          path.startsWith('https:') ||
+          path.startsWith('package:') ||
+          path.startsWith('dart:') ||
+          path.startsWith('data:') ||
+          path.startsWith('file:')) {
+        return Uri.parse(path);
+      } else {
+        return Uri.base.resolveUri(new Uri.file(path));
+      }
+    });
+  }
+}
diff --git a/sdk_nnbd/lib/_internal/vm/bin/process_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/process_patch.dart
new file mode 100644
index 0000000..046377d
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/bin/process_patch.dart
@@ -0,0 +1,644 @@
+// 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 "common_patch.dart";
+
+@patch
+class _WindowsCodePageDecoder {
+  @patch
+  static String _decodeBytes(List<int> bytes) native "SystemEncodingToString";
+}
+
+@patch
+class _WindowsCodePageEncoder {
+  @patch
+  static List<int> _encodeString(String string) native "StringToSystemEncoding";
+}
+
+@patch
+class Process {
+  @patch
+  static Future<Process> start(String executable, List<String> arguments,
+      {String workingDirectory,
+      Map<String, String> environment,
+      bool includeParentEnvironment: true,
+      bool runInShell: false,
+      ProcessStartMode mode: ProcessStartMode.normal}) {
+    _ProcessImpl process = new _ProcessImpl(
+        executable,
+        arguments,
+        workingDirectory,
+        environment,
+        includeParentEnvironment,
+        runInShell,
+        mode);
+    return process._start();
+  }
+
+  @patch
+  static Future<ProcessResult> run(String executable, List<String> arguments,
+      {String workingDirectory,
+      Map<String, String> environment,
+      bool includeParentEnvironment: true,
+      bool runInShell: false,
+      Encoding stdoutEncoding: systemEncoding,
+      Encoding stderrEncoding: systemEncoding}) {
+    return _runNonInteractiveProcess(
+        executable,
+        arguments,
+        workingDirectory,
+        environment,
+        includeParentEnvironment,
+        runInShell,
+        stdoutEncoding,
+        stderrEncoding);
+  }
+
+  @patch
+  static ProcessResult runSync(String executable, List<String> arguments,
+      {String workingDirectory,
+      Map<String, String> environment,
+      bool includeParentEnvironment: true,
+      bool runInShell: false,
+      Encoding stdoutEncoding: systemEncoding,
+      Encoding stderrEncoding: systemEncoding}) {
+    return _runNonInteractiveProcessSync(
+        executable,
+        arguments,
+        workingDirectory,
+        environment,
+        includeParentEnvironment,
+        runInShell,
+        stdoutEncoding,
+        stderrEncoding);
+  }
+
+  @patch
+  static bool killPid(int pid, [ProcessSignal signal = ProcessSignal.sigterm]) {
+    if (signal is! ProcessSignal) {
+      throw new ArgumentError("Argument 'signal' must be a ProcessSignal");
+    }
+    return _ProcessUtils._killPid(pid, signal._signalNumber);
+  }
+}
+
+List<_SignalController> _signalControllers = new List(32);
+
+class _SignalController {
+  final ProcessSignal signal;
+
+  StreamController<ProcessSignal> _controller;
+  var _id;
+
+  _SignalController(this.signal) {
+    _controller = new StreamController<ProcessSignal>.broadcast(
+        onListen: _listen, onCancel: _cancel);
+  }
+
+  Stream<ProcessSignal> get stream => _controller.stream;
+
+  void _listen() {
+    var id = _setSignalHandler(signal._signalNumber);
+    if (id is! int) {
+      _controller
+          .addError(new SignalException("Failed to listen for $signal", id));
+      return;
+    }
+    _id = id;
+    var socket = new _RawSocket(new _NativeSocket.watchSignal(id));
+    socket.listen((event) {
+      if (event == RawSocketEvent.read) {
+        var bytes = socket.read();
+        for (int i = 0; i < bytes.length; i++) {
+          _controller.add(signal);
+        }
+      }
+    });
+  }
+
+  void _cancel() {
+    if (_id != null) {
+      _clearSignalHandler(signal._signalNumber);
+      _id = null;
+    }
+  }
+
+  static _setSignalHandler(int signal) native "Process_SetSignalHandler";
+  static int _clearSignalHandler(int signal)
+      native "Process_ClearSignalHandler";
+}
+
+@pragma("vm:entry-point", "call")
+Function _getWatchSignalInternal() => _ProcessUtils._watchSignalInternal;
+
+@patch
+class _ProcessUtils {
+  @patch
+  static void _exit(int status) native "Process_Exit";
+  @patch
+  static void _setExitCode(int status) native "Process_SetExitCode";
+  @patch
+  static int _getExitCode() native "Process_GetExitCode";
+  @patch
+  static void _sleep(int millis) native "Process_Sleep";
+  @patch
+  static int _pid(Process process) native "Process_Pid";
+  static bool _killPid(int pid, int signal) native "Process_KillPid";
+  @patch
+  static Stream<ProcessSignal> _watchSignal(ProcessSignal signal) {
+    if (signal != ProcessSignal.sighup &&
+        signal != ProcessSignal.sigint &&
+        signal != ProcessSignal.sigterm &&
+        (Platform.isWindows ||
+            (signal != ProcessSignal.sigusr1 &&
+                signal != ProcessSignal.sigusr2 &&
+                signal != ProcessSignal.sigwinch))) {
+      throw new SignalException(
+          "Listening for signal $signal is not supported");
+    }
+    return _watchSignalInternal(signal);
+  }
+
+  static Stream<ProcessSignal> _watchSignalInternal(ProcessSignal signal) {
+    if (_signalControllers[signal._signalNumber] == null) {
+      _signalControllers[signal._signalNumber] = new _SignalController(signal);
+    }
+    return _signalControllers[signal._signalNumber].stream;
+  }
+}
+
+@patch
+class ProcessInfo {
+  @patch
+  static int get maxRss {
+    var result = _maxRss();
+    if (result is OSError) {
+      throw result;
+    }
+    return result;
+  }
+
+  @patch
+  static int get currentRss {
+    var result = _currentRss();
+    if (result is OSError) {
+      throw result;
+    }
+    return result;
+  }
+
+  static _maxRss() native "ProcessInfo_MaxRSS";
+  static _currentRss() native "ProcessInfo_CurrentRSS";
+}
+
+@pragma("vm:entry-point")
+class _ProcessStartStatus {
+  @pragma("vm:entry-point", "set")
+  int _errorCode; // Set to OS error code if process start failed.
+  @pragma("vm:entry-point", "set")
+  String _errorMessage; // Set to OS error message if process start failed.
+}
+
+// The NativeFieldWrapperClass1 can not be used with a mixin, due to missing
+// implicit constructor.
+class _ProcessImplNativeWrapper extends NativeFieldWrapperClass1 {}
+
+class _ProcessImpl extends _ProcessImplNativeWrapper implements Process {
+  _ProcessResourceInfo _resourceInfo;
+  static bool connectedResourceHandler = false;
+
+  _ProcessImpl(
+      String path,
+      List<String> arguments,
+      this._workingDirectory,
+      Map<String, String> environment,
+      bool includeParentEnvironment,
+      bool runInShell,
+      ProcessStartMode mode)
+      : super() {
+    if (!connectedResourceHandler) {
+      registerExtension(
+          'ext.dart.io.getProcesses', _ProcessResourceInfo.getStartedProcesses);
+      registerExtension('ext.dart.io.getProcessById',
+          _ProcessResourceInfo.getProcessInfoMapById);
+      connectedResourceHandler = true;
+    }
+
+    if (runInShell) {
+      arguments = _getShellArguments(path, arguments);
+      path = _getShellCommand();
+    }
+
+    if (path is! String) {
+      throw new ArgumentError("Path is not a String: $path");
+    }
+
+    if (Platform.isWindows && path.contains(' ') && !path.contains('"')) {
+      // Escape paths that may contain spaces
+      // Bug: https://github.com/dart-lang/sdk/issues/37751
+      _path = '"$path"';
+    } else {
+      _path = path;
+    }
+
+    if (arguments is! List) {
+      throw new ArgumentError("Arguments is not a List: $arguments");
+    }
+    int len = arguments.length;
+    _arguments = new List<String>(len);
+    for (int i = 0; i < len; i++) {
+      var arg = arguments[i];
+      if (arg is! String) {
+        throw new ArgumentError("Non-string argument: $arg");
+      }
+      _arguments[i] = arguments[i];
+      if (Platform.isWindows) {
+        _arguments[i] = _windowsArgumentEscape(_arguments[i]);
+      }
+    }
+
+    if (_workingDirectory != null && _workingDirectory is! String) {
+      throw new ArgumentError(
+          "WorkingDirectory is not a String: $_workingDirectory");
+    }
+
+    _environment = [];
+    // Ensure that we have a non-null environment.
+    environment = (environment == null) ? (const {}) : environment;
+    if (environment is! Map) {
+      throw new ArgumentError("Environment is not a map: $environment");
+    }
+    environment.forEach((key, value) {
+      if (key is! String || value is! String) {
+        throw new ArgumentError(
+            "Environment key or value is not a string: ($key, $value)");
+      }
+      _environment.add('$key=$value');
+    });
+    if (includeParentEnvironment) {
+      Platform.environment.forEach((key, value) {
+        assert(key is String);
+        assert(value is String);
+        // Do not override keys already set as part of environment.
+        if (!environment.containsKey(key)) {
+          _environment.add('$key=$value');
+        }
+      });
+    }
+
+    if (mode is! ProcessStartMode) {
+      throw new ArgumentError("Mode is not a ProcessStartMode: $mode");
+    }
+    _mode = mode;
+
+    if (_modeHasStdio(mode)) {
+      // stdin going to process.
+      _stdin = new _StdSink(new _Socket._writePipe().._owner = this);
+      // stdout coming from process.
+      _stdout = new _StdStream(new _Socket._readPipe().._owner = this);
+      // stderr coming from process.
+      _stderr = new _StdStream(new _Socket._readPipe().._owner = this);
+    }
+    if (_modeIsAttached(mode)) {
+      _exitHandler = new _Socket._readPipe();
+    }
+    _ended = false;
+    _started = false;
+  }
+
+  _NativeSocket get _stdinNativeSocket =>
+      (_stdin._sink as _Socket)._nativeSocket;
+  _NativeSocket get _stdoutNativeSocket =>
+      (_stdout._stream as _Socket)._nativeSocket;
+  _NativeSocket get _stderrNativeSocket =>
+      (_stderr._stream as _Socket)._nativeSocket;
+
+  static bool _modeIsAttached(ProcessStartMode mode) {
+    return (mode == ProcessStartMode.normal) ||
+        (mode == ProcessStartMode.inheritStdio);
+  }
+
+  static bool _modeHasStdio(ProcessStartMode mode) {
+    return (mode == ProcessStartMode.normal) ||
+        (mode == ProcessStartMode.detachedWithStdio);
+  }
+
+  static String _getShellCommand() {
+    if (Platform.isWindows) {
+      return 'cmd.exe';
+    }
+    return '/bin/sh';
+  }
+
+  static List<String> _getShellArguments(
+      String executable, List<String> arguments) {
+    List<String> shellArguments = [];
+    if (Platform.isWindows) {
+      shellArguments.add('/c');
+      shellArguments.add(executable);
+      for (var arg in arguments) {
+        shellArguments.add(arg);
+      }
+    } else {
+      var commandLine = new StringBuffer();
+      executable = executable.replaceAll("'", "'\"'\"'");
+      commandLine.write("'$executable'");
+      shellArguments.add("-c");
+      for (var arg in arguments) {
+        arg = arg.replaceAll("'", "'\"'\"'");
+        commandLine.write(" '$arg'");
+      }
+      shellArguments.add(commandLine.toString());
+    }
+    return shellArguments;
+  }
+
+  String _windowsArgumentEscape(String argument) {
+    var result = argument;
+    if (argument.contains('\t') ||
+        argument.contains(' ') ||
+        argument.contains('"')) {
+      // Produce something that the C runtime on Windows will parse
+      // back as this string.
+
+      // Replace any number of '\' followed by '"' with
+      // twice as many '\' followed by '\"'.
+      var backslash = '\\'.codeUnitAt(0);
+      var sb = new StringBuffer();
+      var nextPos = 0;
+      var quotePos = argument.indexOf('"', nextPos);
+      while (quotePos != -1) {
+        var numBackslash = 0;
+        var pos = quotePos - 1;
+        while (pos >= 0 && argument.codeUnitAt(pos) == backslash) {
+          numBackslash++;
+          pos--;
+        }
+        sb.write(argument.substring(nextPos, quotePos - numBackslash));
+        for (var i = 0; i < numBackslash; i++) {
+          sb.write(r'\\');
+        }
+        sb.write(r'\"');
+        nextPos = quotePos + 1;
+        quotePos = argument.indexOf('"', nextPos);
+      }
+      sb.write(argument.substring(nextPos, argument.length));
+      result = sb.toString();
+
+      // Add '"' at the beginning and end and replace all '\' at
+      // the end with two '\'.
+      sb = new StringBuffer('"');
+      sb.write(result);
+      nextPos = argument.length - 1;
+      while (argument.codeUnitAt(nextPos) == backslash) {
+        sb.write('\\');
+        nextPos--;
+      }
+      sb.write('"');
+      result = sb.toString();
+    }
+
+    return result;
+  }
+
+  int _intFromBytes(List<int> bytes, int offset) {
+    return (bytes[offset] +
+        (bytes[offset + 1] << 8) +
+        (bytes[offset + 2] << 16) +
+        (bytes[offset + 3] << 24));
+  }
+
+  Future<Process> _start() {
+    var completer = new Completer<Process>();
+    if (_modeIsAttached(_mode)) {
+      _exitCode = new Completer<int>();
+    }
+    // TODO(ager): Make the actual process starting really async instead of
+    // simulating it with a timer.
+    Timer.run(() {
+      var status = new _ProcessStartStatus();
+      bool success = _startNative(
+          _Namespace._namespace,
+          _path,
+          _arguments,
+          _workingDirectory,
+          _environment,
+          _mode._mode,
+          _modeHasStdio(_mode) ? _stdinNativeSocket : null,
+          _modeHasStdio(_mode) ? _stdoutNativeSocket : null,
+          _modeHasStdio(_mode) ? _stderrNativeSocket : null,
+          _modeIsAttached(_mode) ? _exitHandler._nativeSocket : null,
+          status);
+      if (!success) {
+        completer.completeError(new ProcessException(
+            _path, _arguments, status._errorMessage, status._errorCode));
+        return;
+      }
+
+      _started = true;
+      _resourceInfo = new _ProcessResourceInfo(this);
+
+      // Setup an exit handler to handle internal cleanup and possible
+      // callback when a process terminates.
+      if (_modeIsAttached(_mode)) {
+        int exitDataRead = 0;
+        final int EXIT_DATA_SIZE = 8;
+        List<int> exitDataBuffer = new List<int>(EXIT_DATA_SIZE);
+        _exitHandler.listen((data) {
+          int exitCode(List<int> ints) {
+            var code = _intFromBytes(ints, 0);
+            var negative = _intFromBytes(ints, 4);
+            assert(negative == 0 || negative == 1);
+            return (negative == 0) ? code : -code;
+          }
+
+          void handleExit() {
+            _ended = true;
+            _exitCode.complete(exitCode(exitDataBuffer));
+            // Kill stdin, helping hand if the user forgot to do it.
+            if (_modeHasStdio(_mode)) {
+              (_stdin._sink as _Socket).destroy();
+            }
+            _resourceInfo.stopped();
+          }
+
+          exitDataBuffer.setRange(
+              exitDataRead, exitDataRead + data.length, data);
+          exitDataRead += data.length;
+          if (exitDataRead == EXIT_DATA_SIZE) {
+            handleExit();
+          }
+        });
+      }
+
+      completer.complete(this);
+    });
+    return completer.future;
+  }
+
+  ProcessResult _runAndWait(Encoding stdoutEncoding, Encoding stderrEncoding) {
+    var status = new _ProcessStartStatus();
+    _exitCode = new Completer<int>();
+    bool success = _startNative(
+        _Namespace._namespace,
+        _path,
+        _arguments,
+        _workingDirectory,
+        _environment,
+        ProcessStartMode.normal._mode,
+        _stdinNativeSocket,
+        _stdoutNativeSocket,
+        _stderrNativeSocket,
+        _exitHandler._nativeSocket,
+        status);
+    if (!success) {
+      throw new ProcessException(
+          _path, _arguments, status._errorMessage, status._errorCode);
+    }
+
+    _resourceInfo = new _ProcessResourceInfo(this);
+
+    var result = _wait(_stdinNativeSocket, _stdoutNativeSocket,
+        _stderrNativeSocket, _exitHandler._nativeSocket);
+
+    getOutput(output, encoding) {
+      if (encoding == null) return output;
+      return encoding.decode(output);
+    }
+
+    _resourceInfo.stopped();
+
+    return new ProcessResult(
+        result[0],
+        result[1],
+        getOutput(result[2], stdoutEncoding),
+        getOutput(result[3], stderrEncoding));
+  }
+
+  bool _startNative(
+      _Namespace namespace,
+      String path,
+      List<String> arguments,
+      String workingDirectory,
+      List<String> environment,
+      int mode,
+      _NativeSocket stdin,
+      _NativeSocket stdout,
+      _NativeSocket stderr,
+      _NativeSocket exitHandler,
+      _ProcessStartStatus status) native "Process_Start";
+
+  _wait(_NativeSocket stdin, _NativeSocket stdout, _NativeSocket stderr,
+      _NativeSocket exitHandler) native "Process_Wait";
+
+  Stream<List<int>> get stdout {
+    return _stdout;
+  }
+
+  Stream<List<int>> get stderr {
+    return _stderr;
+  }
+
+  IOSink get stdin {
+    return _stdin;
+  }
+
+  Future<int> get exitCode => _exitCode != null ? _exitCode.future : null;
+
+  bool kill([ProcessSignal signal = ProcessSignal.sigterm]) {
+    if (signal is! ProcessSignal) {
+      throw new ArgumentError("Argument 'signal' must be a ProcessSignal");
+    }
+    assert(_started);
+    if (_ended) return false;
+    return _ProcessUtils._killPid(pid, signal._signalNumber);
+  }
+
+  int get pid => _ProcessUtils._pid(this);
+
+  String _path;
+  List<String> _arguments;
+  String _workingDirectory;
+  List<String> _environment;
+  ProcessStartMode _mode;
+  // Private methods of Socket are used by _in, _out, and _err.
+  _StdSink _stdin;
+  _StdStream _stdout;
+  _StdStream _stderr;
+  _Socket _exitHandler;
+  bool _ended;
+  bool _started;
+  Completer<int> _exitCode;
+}
+
+// _NonInteractiveProcess is a wrapper around an interactive process
+// that buffers output so it can be delivered when the process exits.
+// _NonInteractiveProcess is used to implement the Process.run
+// method.
+Future<ProcessResult> _runNonInteractiveProcess(
+    String path,
+    List<String> arguments,
+    String workingDirectory,
+    Map<String, String> environment,
+    bool includeParentEnvironment,
+    bool runInShell,
+    Encoding stdoutEncoding,
+    Encoding stderrEncoding) {
+  // Start the underlying process.
+  return Process.start(path, arguments,
+          workingDirectory: workingDirectory,
+          environment: environment,
+          includeParentEnvironment: includeParentEnvironment,
+          runInShell: runInShell)
+      .then((Process p) {
+    int pid = p.pid;
+
+    // Make sure the process stdin is closed.
+    p.stdin.close();
+
+    // Setup stdout and stderr handling.
+    Future foldStream(Stream<List<int>> stream, Encoding encoding) {
+      if (encoding == null) {
+        return stream
+            .fold(new BytesBuilder(), (builder, data) => builder..add(data))
+            .then((builder) => builder.takeBytes());
+      } else {
+        return stream.transform(encoding.decoder).fold(new StringBuffer(),
+            (buf, data) {
+          buf.write(data);
+          return buf;
+        }).then((sb) => sb.toString());
+      }
+    }
+
+    Future stdout = foldStream(p.stdout, stdoutEncoding);
+    Future stderr = foldStream(p.stderr, stderrEncoding);
+
+    return Future.wait([p.exitCode, stdout, stderr]).then((result) {
+      return new ProcessResult(pid, result[0], result[1], result[2]);
+    });
+  });
+}
+
+ProcessResult _runNonInteractiveProcessSync(
+    String executable,
+    List<String> arguments,
+    String workingDirectory,
+    Map<String, String> environment,
+    bool includeParentEnvironment,
+    bool runInShell,
+    Encoding stdoutEncoding,
+    Encoding stderrEncoding) {
+  var process = new _ProcessImpl(
+      executable,
+      arguments,
+      workingDirectory,
+      environment,
+      includeParentEnvironment,
+      runInShell,
+      ProcessStartMode.normal);
+  return process._runAndWait(stdoutEncoding, stderrEncoding);
+}
diff --git a/sdk_nnbd/lib/_internal/vm/bin/secure_socket_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/secure_socket_patch.dart
new file mode 100644
index 0000000..8969aa4
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/bin/secure_socket_patch.dart
@@ -0,0 +1,253 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "common_patch.dart";
+
+@patch
+class SecureSocket {
+  @patch
+  factory SecureSocket._(RawSecureSocket rawSocket) =>
+      new _SecureSocket(rawSocket);
+}
+
+@patch
+class _SecureFilter {
+  @patch
+  factory _SecureFilter._() => new _SecureFilterImpl._();
+}
+
+@patch
+@pragma("vm:entry-point")
+class X509Certificate {
+  @patch
+  @pragma("vm:entry-point")
+  factory X509Certificate._() => new _X509CertificateImpl._();
+}
+
+class _SecureSocket extends _Socket implements SecureSocket {
+  _RawSecureSocket get _raw => super._raw as _RawSecureSocket;
+
+  _SecureSocket(RawSecureSocket raw) : super(raw);
+
+  void renegotiate(
+      {bool useSessionCache: true,
+      bool requestClientCertificate: false,
+      bool requireClientCertificate: false}) {
+    _raw.renegotiate(
+        useSessionCache: useSessionCache,
+        requestClientCertificate: requestClientCertificate,
+        requireClientCertificate: requireClientCertificate);
+  }
+
+  X509Certificate get peerCertificate {
+    if (_raw == null) {
+      throw new StateError("peerCertificate called on destroyed SecureSocket");
+    }
+    return _raw.peerCertificate;
+  }
+
+  String get selectedProtocol {
+    if (_raw == null) {
+      throw new StateError("selectedProtocol called on destroyed SecureSocket");
+    }
+    return _raw.selectedProtocol;
+  }
+}
+
+/**
+ * _SecureFilterImpl wraps a filter that encrypts and decrypts data travelling
+ * over an encrypted socket.  The filter also handles the handshaking
+ * and certificate verification.
+ *
+ * The filter exposes its input and output buffers as Dart objects that
+ * are backed by an external C array of bytes, so that both Dart code and
+ * native code can access the same data.
+ */
+@pragma("vm:entry-point")
+class _SecureFilterImpl extends NativeFieldWrapperClass1
+    implements _SecureFilter {
+  // Performance is improved if a full buffer of plaintext fits
+  // in the encrypted buffer, when encrypted.
+  // SIZE and ENCRYPTED_SIZE are referenced from C++.
+  @pragma("vm:entry-point")
+  static final int SIZE = 8 * 1024;
+  @pragma("vm:entry-point")
+  static final int ENCRYPTED_SIZE = 10 * 1024;
+
+  _SecureFilterImpl._() {
+    buffers = new List<_ExternalBuffer>(_RawSecureSocket.bufferCount);
+    for (int i = 0; i < _RawSecureSocket.bufferCount; ++i) {
+      buffers[i] = new _ExternalBuffer(
+          _RawSecureSocket._isBufferEncrypted(i) ? ENCRYPTED_SIZE : SIZE);
+    }
+  }
+
+  void connect(
+      String hostName,
+      SecurityContext context,
+      bool is_server,
+      bool requestClientCertificate,
+      bool requireClientCertificate,
+      Uint8List protocols) native "SecureSocket_Connect";
+
+  void destroy() {
+    buffers = null;
+    _destroy();
+  }
+
+  void _destroy() native "SecureSocket_Destroy";
+
+  void handshake() native "SecureSocket_Handshake";
+
+  void rehandshake() => throw new UnimplementedError();
+
+  int processBuffer(int bufferIndex) => throw new UnimplementedError();
+
+  String selectedProtocol() native "SecureSocket_GetSelectedProtocol";
+
+  void renegotiate(bool useSessionCache, bool requestClientCertificate,
+      bool requireClientCertificate) native "SecureSocket_Renegotiate";
+
+  void init() native "SecureSocket_Init";
+
+  X509Certificate get peerCertificate native "SecureSocket_PeerCertificate";
+
+  void registerBadCertificateCallback(Function callback)
+      native "SecureSocket_RegisterBadCertificateCallback";
+
+  void registerHandshakeCompleteCallback(Function handshakeCompleteHandler)
+      native "SecureSocket_RegisterHandshakeCompleteCallback";
+
+  // This is a security issue, as it exposes a raw pointer to Dart code.
+  int _pointer() native "SecureSocket_FilterPointer";
+
+  @pragma("vm:entry-point", "get")
+  List<_ExternalBuffer> buffers;
+}
+
+@patch
+class SecurityContext {
+  @patch
+  factory SecurityContext({bool withTrustedRoots: false}) {
+    return new _SecurityContext(withTrustedRoots);
+  }
+
+  @patch
+  static SecurityContext get defaultContext {
+    return _SecurityContext.defaultContext;
+  }
+
+  @patch
+  static bool get alpnSupported => true;
+}
+
+class _SecurityContext extends NativeFieldWrapperClass1
+    implements SecurityContext {
+  _SecurityContext(bool withTrustedRoots) {
+    _createNativeContext();
+    if (withTrustedRoots) {
+      _trustBuiltinRoots();
+    }
+  }
+
+  void _createNativeContext() native "SecurityContext_Allocate";
+
+  static final SecurityContext defaultContext = new _SecurityContext(true);
+
+  void usePrivateKey(String file, {String password}) {
+    List<int> bytes = (new File(file)).readAsBytesSync();
+    usePrivateKeyBytes(bytes, password: password);
+  }
+
+  void usePrivateKeyBytes(List<int> keyBytes, {String password})
+      native "SecurityContext_UsePrivateKeyBytes";
+
+  void setTrustedCertificates(String file, {String password}) {
+    List<int> bytes = (new File(file)).readAsBytesSync();
+    setTrustedCertificatesBytes(bytes, password: password);
+  }
+
+  void setTrustedCertificatesBytes(List<int> certBytes, {String password})
+      native "SecurityContext_SetTrustedCertificatesBytes";
+
+  void useCertificateChain(String file, {String password}) {
+    List<int> bytes = (new File(file)).readAsBytesSync();
+    useCertificateChainBytes(bytes, password: password);
+  }
+
+  void useCertificateChainBytes(List<int> chainBytes, {String password})
+      native "SecurityContext_UseCertificateChainBytes";
+
+  void setClientAuthorities(String file, {String password}) {
+    List<int> bytes = (new File(file)).readAsBytesSync();
+    setClientAuthoritiesBytes(bytes, password: password);
+  }
+
+  void setClientAuthoritiesBytes(List<int> authCertBytes, {String password})
+      native "SecurityContext_SetClientAuthoritiesBytes";
+
+  void setAlpnProtocols(List<String> protocols, bool isServer) {
+    Uint8List encodedProtocols =
+        SecurityContext._protocolsToLengthEncoding(protocols);
+    _setAlpnProtocols(encodedProtocols, isServer);
+  }
+
+  void _setAlpnProtocols(Uint8List protocols, bool isServer)
+      native "SecurityContext_SetAlpnProtocols";
+  void _trustBuiltinRoots() native "SecurityContext_TrustBuiltinRoots";
+}
+
+/**
+ * _X509CertificateImpl wraps an X509 certificate object held by the BoringSSL
+ * library. It exposes the fields of the certificate object.
+ */
+class _X509CertificateImpl extends NativeFieldWrapperClass1
+    implements X509Certificate {
+  // The native field must be set manually on a new object, in native code.
+  // This is done by WrappedX509 in secure_socket.cc.
+  _X509CertificateImpl._();
+
+  Uint8List _cachedDer;
+  Uint8List get _der native "X509_Der";
+  Uint8List get der {
+    if (_cachedDer == null) {
+      _cachedDer = _der;
+    }
+    return _cachedDer;
+  }
+
+  String _cachedPem;
+  String get _pem native "X509_Pem";
+  String get pem {
+    if (_cachedPem == null) {
+      _cachedPem = _pem;
+    }
+    return _cachedPem;
+  }
+
+  Uint8List _cachedSha1;
+  Uint8List get _sha1 native "X509_Sha1";
+  Uint8List get sha1 {
+    if (_cachedSha1 == null) {
+      _cachedSha1 = _sha1;
+    }
+    return _cachedSha1;
+  }
+
+  String get subject native "X509_Subject";
+  String get issuer native "X509_Issuer";
+  DateTime get startValidity {
+    return new DateTime.fromMillisecondsSinceEpoch(_startValidity(),
+        isUtc: true);
+  }
+
+  DateTime get endValidity {
+    return new DateTime.fromMillisecondsSinceEpoch(_endValidity(), isUtc: true);
+  }
+
+  int _startValidity() native "X509_StartValidity";
+  int _endValidity() native "X509_EndValidity";
+}
diff --git a/sdk_nnbd/lib/_internal/vm/bin/socket_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/socket_patch.dart
new file mode 100644
index 0000000..f4136a0
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/bin/socket_patch.dart
@@ -0,0 +1,2041 @@
+// 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 "common_patch.dart";
+
+@patch
+class RawServerSocket {
+  @patch
+  static Future<RawServerSocket> bind(address, int port,
+      {int backlog: 0, bool v6Only: false, bool shared: false}) {
+    return _RawServerSocket.bind(address, port, backlog, v6Only, shared);
+  }
+}
+
+@patch
+class RawSocket {
+  @patch
+  static Future<RawSocket> connect(host, int port,
+      {sourceAddress, Duration timeout}) {
+    return _RawSocket.connect(host, port, sourceAddress, timeout);
+  }
+
+  @patch
+  static Future<ConnectionTask<RawSocket>> startConnect(host, int port,
+      {sourceAddress}) {
+    return _RawSocket.startConnect(host, port, sourceAddress);
+  }
+}
+
+@patch
+class RawSocketOption {
+  static final List<int> _optionsCache =
+      List<int>(_RawSocketOptions.values.length);
+
+  @patch
+  static int _getOptionValue(int key) {
+    if (key > _RawSocketOptions.values.length) {
+      throw ArgumentError.value(key, 'key');
+    }
+    _optionsCache[key] ??= _getNativeOptionValue(key);
+    return _optionsCache[key];
+  }
+
+  static int _getNativeOptionValue(int key)
+      native "RawSocketOption_GetOptionValue";
+}
+
+@patch
+class InternetAddress {
+  @patch
+  static InternetAddress get LOOPBACK_IP_V4 {
+    return _InternetAddress.loopbackIPv4;
+  }
+
+  @patch
+  static InternetAddress get LOOPBACK_IP_V6 {
+    return _InternetAddress.loopbackIPv6;
+  }
+
+  @patch
+  static InternetAddress get ANY_IP_V4 {
+    return _InternetAddress.anyIPv4;
+  }
+
+  @patch
+  static InternetAddress get ANY_IP_V6 {
+    return _InternetAddress.anyIPv6;
+  }
+
+  @patch
+  factory InternetAddress(String address) {
+    return new _InternetAddress.parse(address);
+  }
+
+  @patch
+  static Future<List<InternetAddress>> lookup(String host,
+      {InternetAddressType type: InternetAddressType.any}) {
+    return _NativeSocket.lookup(host, type: type);
+  }
+
+  @patch
+  static InternetAddress _cloneWithNewHost(
+      InternetAddress address, String host) {
+    return (address as _InternetAddress)._cloneWithNewHost(host);
+  }
+}
+
+@patch
+class NetworkInterface {
+  @patch
+  static bool get listSupported {
+    return _listSupported();
+  }
+
+  @patch
+  static Future<List<NetworkInterface>> list(
+      {bool includeLoopback: false,
+      bool includeLinkLocal: false,
+      InternetAddressType type: InternetAddressType.any}) {
+    return _NativeSocket.listInterfaces(
+        includeLoopback: includeLoopback,
+        includeLinkLocal: includeLinkLocal,
+        type: type);
+  }
+
+  static bool _listSupported() native "NetworkInterface_ListSupported";
+}
+
+void _throwOnBadPort(int port) {
+  if ((port == null) || (port < 0) || (port > 0xFFFF)) {
+    throw new ArgumentError("Invalid port $port");
+  }
+}
+
+void _throwOnBadTtl(int ttl) {
+  if (ttl == null || ttl < 1 || ttl > 255) {
+    throw new ArgumentError('Invalid ttl $ttl');
+  }
+}
+
+class _InternetAddress implements InternetAddress {
+  static const int _addressLoopbackIPv4 = 0;
+  static const int _addressLoopbackIPv6 = 1;
+  static const int _addressAnyIPv4 = 2;
+  static const int _addressAnyIPv6 = 3;
+  static const int _IPv4AddrLength = 4;
+  static const int _IPv6AddrLength = 16;
+
+  static _InternetAddress loopbackIPv4 =
+      new _InternetAddress.fixed(_addressLoopbackIPv4);
+  static _InternetAddress loopbackIPv6 =
+      new _InternetAddress.fixed(_addressLoopbackIPv6);
+  static _InternetAddress anyIPv4 = new _InternetAddress.fixed(_addressAnyIPv4);
+  static _InternetAddress anyIPv6 = new _InternetAddress.fixed(_addressAnyIPv6);
+
+  final String address;
+  final String _host;
+  final Uint8List _in_addr;
+  final int _scope_id;
+
+  InternetAddressType get type => _in_addr.length == _IPv4AddrLength
+      ? InternetAddressType.IPv4
+      : InternetAddressType.IPv6;
+
+  String get host => _host != null ? _host : address;
+
+  Uint8List get rawAddress => new Uint8List.fromList(_in_addr);
+
+  bool get isLoopback {
+    switch (type) {
+      case InternetAddressType.IPv4:
+        return _in_addr[0] == 127;
+
+      case InternetAddressType.IPv6:
+        for (int i = 0; i < _IPv6AddrLength - 1; i++) {
+          if (_in_addr[i] != 0) return false;
+        }
+        return _in_addr[_IPv6AddrLength - 1] == 1;
+    }
+  }
+
+  bool get isLinkLocal {
+    switch (type) {
+      case InternetAddressType.IPv4:
+        // Checking for 169.254.0.0/16.
+        return _in_addr[0] == 169 && _in_addr[1] == 254;
+
+      case InternetAddressType.IPv6:
+        // Checking for fe80::/10.
+        return _in_addr[0] == 0xFE && (_in_addr[1] & 0xB0) == 0x80;
+    }
+  }
+
+  bool get isMulticast {
+    switch (type) {
+      case InternetAddressType.IPv4:
+        // Checking for 224.0.0.0 through 239.255.255.255.
+        return _in_addr[0] >= 224 && _in_addr[0] < 240;
+
+      case InternetAddressType.IPv6:
+        // Checking for ff00::/8.
+        return _in_addr[0] == 0xFF;
+    }
+  }
+
+  Future<InternetAddress> reverse() => _NativeSocket.reverseLookup(this);
+
+  _InternetAddress(this.address, this._host, this._in_addr,
+      [this._scope_id = 0]);
+
+  factory _InternetAddress.parse(String address) {
+    if (address is! String) {
+      throw new ArgumentError("Invalid internet address $address");
+    }
+    var in_addr = _parse(address);
+    if (in_addr == null) {
+      throw new ArgumentError("Invalid internet address $address");
+    }
+    return new _InternetAddress(address, null, in_addr);
+  }
+
+  factory _InternetAddress.fixed(int id) {
+    switch (id) {
+      case _addressLoopbackIPv4:
+        var in_addr = new Uint8List(_IPv4AddrLength);
+        in_addr[0] = 127;
+        in_addr[_IPv4AddrLength - 1] = 1;
+        return new _InternetAddress("127.0.0.1", null, in_addr);
+      case _addressLoopbackIPv6:
+        var in_addr = new Uint8List(_IPv6AddrLength);
+        in_addr[_IPv6AddrLength - 1] = 1;
+        return new _InternetAddress("::1", null, in_addr);
+      case _addressAnyIPv4:
+        var in_addr = new Uint8List(_IPv4AddrLength);
+        return new _InternetAddress("0.0.0.0", "0.0.0.0", in_addr);
+      case _addressAnyIPv6:
+        var in_addr = new Uint8List(_IPv6AddrLength);
+        return new _InternetAddress("::", "::", in_addr);
+      default:
+        assert(false);
+        throw new ArgumentError();
+    }
+  }
+
+  // Create a clone of this _InternetAddress replacing the host.
+  _InternetAddress _cloneWithNewHost(String host) {
+    return new _InternetAddress(
+        address, host, new Uint8List.fromList(_in_addr));
+  }
+
+  bool operator ==(other) {
+    if (!(other is _InternetAddress)) return false;
+    if (other.type != type) return false;
+    bool equals = true;
+    for (int i = 0; i < _in_addr.length && equals; i++) {
+      equals = other._in_addr[i] == _in_addr[i];
+    }
+    return equals;
+  }
+
+  int get hashCode {
+    int result = 1;
+    for (int i = 0; i < _in_addr.length; i++) {
+      result = (result * 31 + _in_addr[i]) & 0x3FFFFFFF;
+    }
+    return result;
+  }
+
+  String toString() {
+    return "InternetAddress('$address', ${type.name})";
+  }
+
+  static Uint8List _parse(String address) native "InternetAddress_Parse";
+}
+
+class _NetworkInterface implements NetworkInterface {
+  final String name;
+  final int index;
+  final List<InternetAddress> addresses = [];
+
+  _NetworkInterface(this.name, this.index);
+
+  String toString() {
+    return "NetworkInterface('$name', $addresses)";
+  }
+}
+
+// The NativeFieldWrapperClass1 cannot be used with a mixin, due to missing
+// implicit constructor.
+class _NativeSocketNativeWrapper extends NativeFieldWrapperClass1 {}
+
+// The _NativeSocket class encapsulates an OS socket.
+class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
+  // Bit flags used when communicating between the eventhandler and
+  // dart code. The EVENT flags are used to indicate events of
+  // interest when sending a message from dart code to the
+  // eventhandler. When receiving a message from the eventhandler the
+  // EVENT flags indicate the events that actually happened. The
+  // COMMAND flags are used to send commands from dart to the
+  // eventhandler. COMMAND flags are never received from the
+  // eventhandler. Additional flags are used to communicate other
+  // information.
+  static const int readEvent = 0;
+  static const int writeEvent = 1;
+  static const int errorEvent = 2;
+  static const int closedEvent = 3;
+  static const int destroyedEvent = 4;
+  static const int firstEvent = readEvent;
+  static const int lastEvent = destroyedEvent;
+  static const int eventCount = lastEvent - firstEvent + 1;
+
+  static const int closeCommand = 8;
+  static const int shutdownReadCommand = 9;
+  static const int shutdownWriteCommand = 10;
+  // The lower bits of returnTokenCommand messages contains the number
+  // of tokens returned.
+  static const int returnTokenCommand = 11;
+  static const int setEventMaskCommand = 12;
+  static const int firstCommand = closeCommand;
+  static const int lastCommand = setEventMaskCommand;
+
+  // Type flag send to the eventhandler providing additional
+  // information on the type of the file descriptor.
+  static const int listeningSocket = 16;
+  static const int pipeSocket = 17;
+  static const int typeNormalSocket = 0;
+  static const int typeListeningSocket = 1 << listeningSocket;
+  static const int typePipe = 1 << pipeSocket;
+  static const int typeTypeMask = typeListeningSocket | pipeSocket;
+
+  // Protocol flags.
+  // Keep in sync with SocketType enum in socket.h.
+  static const int tcpSocket = 18;
+  static const int udpSocket = 19;
+  static const int internalSocket = 20;
+  static const int internalSignalSocket = 21;
+  static const int typeTcpSocket = 1 << tcpSocket;
+  static const int typeUdpSocket = 1 << udpSocket;
+  static const int typeInternalSocket = 1 << internalSocket;
+  static const int typeInternalSignalSocket = 1 << internalSignalSocket;
+  static const int typeProtocolMask = typeTcpSocket |
+      typeUdpSocket |
+      typeInternalSocket |
+      typeInternalSignalSocket;
+
+  // Native port messages.
+  static const hostNameLookupMessage = 0;
+  static const listInterfacesMessage = 1;
+  static const reverseLookupMessage = 2;
+
+  // Protocol flags.
+  static const int protocolIPv4 = 1 << 0;
+  static const int protocolIPv6 = 1 << 1;
+
+  static const int normalTokenBatchSize = 8;
+  static const int listeningTokenBatchSize = 2;
+
+  static const Duration _retryDuration = const Duration(milliseconds: 250);
+  static const Duration _retryDurationLoopback =
+      const Duration(milliseconds: 25);
+
+  // Socket close state
+  bool isClosed = false;
+  bool isClosing = false;
+  bool isClosedRead = false;
+  bool closedReadEventSent = false;
+  bool isClosedWrite = false;
+  Completer closeCompleter = new Completer.sync();
+
+  // Handlers and receive port for socket events from the event handler.
+  final List eventHandlers = new List(eventCount + 1);
+  RawReceivePort eventPort;
+  bool flagsSent = false;
+
+  // The type flags for this socket.
+  final int typeFlags;
+
+  // Holds the port of the socket, 0 if not known.
+  int localPort = 0;
+
+  // Holds the address used to connect or bind the socket.
+  InternetAddress localAddress;
+
+  int available = 0;
+
+  int tokens = 0;
+
+  bool sendReadEvents = false;
+  bool readEventIssued = false;
+
+  bool sendWriteEvents = false;
+  bool writeEventIssued = false;
+  bool writeAvailable = false;
+
+  static bool connectedResourceHandler = false;
+  _ReadWriteResourceInfo resourceInfo;
+
+  // The owner object is the object that the Socket is being used by, e.g.
+  // a HttpServer, a WebSocket connection, a process pipe, etc.
+  Object owner;
+
+  static Future<List<InternetAddress>> lookup(String host,
+      {InternetAddressType type: InternetAddressType.any}) {
+    return _IOService._dispatch(_IOService.socketLookup, [host, type._value])
+        .then((response) {
+      if (isErrorResponse(response)) {
+        throw createError(response, "Failed host lookup: '$host'");
+      } else {
+        return response.skip(1).map<InternetAddress>((result) {
+          var type = new InternetAddressType._from(result[0]);
+          return new _InternetAddress(result[1], host, result[2], result[3]);
+        }).toList();
+      }
+    });
+  }
+
+  static Future<InternetAddress> reverseLookup(InternetAddress addr) {
+    return _IOService._dispatch(_IOService.socketReverseLookup,
+        [(addr as _InternetAddress)._in_addr]).then((response) {
+      if (isErrorResponse(response)) {
+        throw createError(response, "Failed reverse host lookup", addr);
+      } else {
+        return (addr as _InternetAddress)._cloneWithNewHost(response);
+      }
+    });
+  }
+
+  static Future<List<NetworkInterface>> listInterfaces(
+      {bool includeLoopback: false,
+      bool includeLinkLocal: false,
+      InternetAddressType type: InternetAddressType.any}) {
+    return _IOService._dispatch(_IOService.socketListInterfaces, [type._value])
+        .then((response) {
+      if (isErrorResponse(response)) {
+        throw createError(response, "Failed listing interfaces");
+      } else {
+        var map = response.skip(1).fold(new Map<String, NetworkInterface>(),
+            (map, result) {
+          var type = new InternetAddressType._from(result[0]);
+          var name = result[3];
+          var index = result[4];
+          var address = new _InternetAddress(result[1], "", result[2]);
+          if (!includeLinkLocal && address.isLinkLocal) return map;
+          if (!includeLoopback && address.isLoopback) return map;
+          map.putIfAbsent(name, () => new _NetworkInterface(name, index));
+          map[name].addresses.add(address);
+          return map;
+        });
+        return map.values.toList();
+      }
+    });
+  }
+
+  static String escapeLinkLocalAddress(String host) {
+    // if the host contains escape, host is an IPv6 address with scope ID.
+    // Remove '25' before feeding into native calls.
+    int index = host.indexOf('%');
+    if (index >= 0) {
+      if (!checkLinkLocalAddress(host)) {
+        // The only well defined usage is link-local address. Checks Section 4 of https://tools.ietf.org/html/rfc6874.
+        // If it is not a valid link-local address and contains escape character, throw an exception.
+        throw new FormatException(
+            '${host} is not a valid link-local address but contains %. Scope id should be used as part of link-local address.',
+            host,
+            index);
+      }
+      if (host.startsWith("25", index + 1)) {
+        // Remove '25' after '%' if present
+        host = host.replaceRange(index + 1, index + 3, '');
+      }
+    }
+    return host;
+  }
+
+  static bool checkLinkLocalAddress(String host) {
+    // The shortest possible link-local address is [fe80::1]
+    if (host.length < 7) return false;
+    var char = host[2];
+    return host.startsWith('fe') &&
+        (char == '8' || char == '9' || char == 'a' || char == 'b');
+  }
+
+  static Future<ConnectionTask<_NativeSocket>> startConnect(
+      host, int port, sourceAddress) {
+    if (host is String) {
+      host = escapeLinkLocalAddress(host);
+    }
+    _throwOnBadPort(port);
+    if (sourceAddress != null && sourceAddress is! _InternetAddress) {
+      if (sourceAddress is String) {
+        sourceAddress = new InternetAddress(sourceAddress);
+      }
+    }
+    return new Future.value(host).then((host) {
+      if (host is _InternetAddress) return [host];
+      return lookup(host).then((addresses) {
+        if (addresses.isEmpty) {
+          throw createError(null, "Failed host lookup: '$host'");
+        }
+        return addresses;
+      });
+    }).then((addresses) {
+      var completer = new Completer<_NativeSocket>();
+      var it = (addresses as List<InternetAddress>).iterator;
+      var error = null;
+      var connecting = new HashMap();
+
+      void connectNext() {
+        if (!it.moveNext()) {
+          if (connecting.isEmpty) {
+            assert(error != null);
+            completer.completeError(error);
+          }
+          return;
+        }
+        final _InternetAddress address = it.current;
+        var socket = new _NativeSocket.normal();
+        socket.localAddress = address;
+        var result;
+        if (sourceAddress == null) {
+          result = socket.nativeCreateConnect(
+              address._in_addr, port, address._scope_id);
+        } else {
+          assert(sourceAddress is _InternetAddress);
+          result = socket.nativeCreateBindConnect(address._in_addr, port,
+              sourceAddress._in_addr, address._scope_id);
+        }
+        if (result is OSError) {
+          // Keep first error, if present.
+          if (error == null) {
+            int errorCode = result.errorCode;
+            if (sourceAddress != null &&
+                errorCode != null &&
+                socket.isBindError(errorCode)) {
+              error = createError(result, "Bind failed", sourceAddress);
+            } else {
+              error = createError(result, "Connection failed", address, port);
+            }
+          }
+          connectNext();
+        } else {
+          // Query the local port for error messages.
+          try {
+            socket.port;
+          } catch (e) {
+            if (error == null) {
+              error = createError(e, "Connection failed", address, port);
+            }
+            connectNext();
+          }
+          // Set up timer for when we should retry the next address
+          // (if any).
+          var duration =
+              address.isLoopback ? _retryDurationLoopback : _retryDuration;
+          var timer = new Timer(duration, connectNext);
+          setupResourceInfo(socket);
+
+          connecting[socket] = timer;
+          // Setup handlers for receiving the first write event which
+          // indicate that the socket is fully connected.
+          socket.setHandlers(write: () {
+            timer.cancel();
+            connecting.remove(socket);
+            // From 'man 2 connect':
+            // After select(2) indicates writability, use getsockopt(2) to read
+            // the SO_ERROR option at level SOL_SOCKET to determine whether
+            // connect() completed successfully (SO_ERROR is zero) or
+            // unsuccessfully.
+            OSError osError = socket.nativeGetError();
+            if (osError.errorCode != 0) {
+              socket.close();
+              if (error == null) error = osError;
+              if (connecting.isEmpty) connectNext();
+              return;
+            }
+            socket.setListening(read: false, write: false);
+            completer.complete(socket);
+            connecting.forEach((s, t) {
+              t.cancel();
+              s.close();
+              s.setHandlers();
+              s.setListening(read: false, write: false);
+            });
+            connecting.clear();
+          }, error: (e, st) {
+            timer.cancel();
+            socket.close();
+            // Keep first error, if present.
+            if (error == null) error = e;
+            connecting.remove(socket);
+            if (connecting.isEmpty) connectNext();
+          });
+          socket.setListening(read: false, write: true);
+        }
+      }
+
+      void onCancel() {
+        connecting.forEach((s, t) {
+          t.cancel();
+          s.close();
+          s.setHandlers();
+          s.setListening(read: false, write: false);
+          if (error == null) {
+            error = createError(null,
+                "Connection attempt cancelled, host: ${host}, port: ${port}");
+          }
+        });
+        connecting.clear();
+        if (!completer.isCompleted) {
+          completer.completeError(error);
+        }
+      }
+
+      connectNext();
+      return new ConnectionTask<_NativeSocket>._(
+          socket: completer.future, onCancel: onCancel);
+    });
+  }
+
+  static Future<_NativeSocket> connect(
+      host, int port, sourceAddress, Duration timeout) {
+    return startConnect(host, port, sourceAddress)
+        .then((ConnectionTask<_NativeSocket> task) {
+      Future<_NativeSocket> socketFuture = task.socket;
+      if (timeout != null) {
+        socketFuture = socketFuture.timeout(timeout, onTimeout: () {
+          task.cancel();
+          throw createError(
+              null, "Connection timed out, host: ${host}, port: ${port}");
+        });
+      }
+      return socketFuture;
+    });
+  }
+
+  static Future<_InternetAddress> _resolveHost(host) async {
+    if (host is _InternetAddress) {
+      return host;
+    } else {
+      final list = await lookup(host);
+      if (list.isEmpty) {
+        throw createError(null, "Failed host lookup: '$host'");
+      }
+      return list.first as _InternetAddress;
+    }
+  }
+
+  static Future<_NativeSocket> bind(
+      host, int port, int backlog, bool v6Only, bool shared) async {
+    _throwOnBadPort(port);
+    if (host is String) {
+      host = escapeLinkLocalAddress(host);
+    }
+    final address = await _resolveHost(host);
+
+    var socket = new _NativeSocket.listen();
+    socket.localAddress = address;
+    var result = socket.nativeCreateBindListen(
+        address._in_addr, port, backlog, v6Only, shared, address._scope_id);
+    if (result is OSError) {
+      throw new SocketException("Failed to create server socket",
+          osError: result, address: address, port: port);
+    }
+    if (port != 0) socket.localPort = port;
+    setupResourceInfo(socket);
+    socket.connectToEventHandler();
+    return socket;
+  }
+
+  static void setupResourceInfo(_NativeSocket socket) {
+    socket.resourceInfo = new _SocketResourceInfo(socket);
+  }
+
+  static Future<_NativeSocket> bindDatagram(
+      host, int port, bool reuseAddress, bool reusePort, int ttl) async {
+    _throwOnBadPort(port);
+    _throwOnBadTtl(ttl);
+
+    final address = await _resolveHost(host);
+
+    var socket = new _NativeSocket.datagram(address);
+    var result = socket.nativeCreateBindDatagram(
+        address._in_addr, port, reuseAddress, reusePort, ttl);
+    if (result is OSError) {
+      throw new SocketException("Failed to create datagram socket",
+          osError: result, address: address, port: port);
+    }
+    if (port != 0) socket.localPort = port;
+    setupResourceInfo(socket);
+    return socket;
+  }
+
+  _NativeSocket.datagram(this.localAddress)
+      : typeFlags = typeNormalSocket | typeUdpSocket;
+
+  _NativeSocket.normal() : typeFlags = typeNormalSocket | typeTcpSocket;
+
+  _NativeSocket.listen() : typeFlags = typeListeningSocket | typeTcpSocket {
+    isClosedWrite = true;
+  }
+
+  _NativeSocket.pipe() : typeFlags = typePipe;
+
+  _NativeSocket._watchCommon(int id, int type)
+      : typeFlags = typeNormalSocket | type {
+    isClosedWrite = true;
+    nativeSetSocketId(id, typeFlags);
+  }
+
+  _NativeSocket.watchSignal(int id)
+      : this._watchCommon(id, typeInternalSignalSocket);
+
+  _NativeSocket.watch(int id) : this._watchCommon(id, typeInternalSocket);
+
+  bool get isListening => (typeFlags & typeListeningSocket) != 0;
+  bool get isPipe => (typeFlags & typePipe) != 0;
+  bool get isInternal => (typeFlags & typeInternalSocket) != 0;
+  bool get isInternalSignal => (typeFlags & typeInternalSignalSocket) != 0;
+  bool get isTcp => (typeFlags & typeTcpSocket) != 0;
+  bool get isUdp => (typeFlags & typeUdpSocket) != 0;
+
+  Map _toJSON(bool ref) => throw new UnimplementedError();
+  String get _serviceTypePath => throw new UnimplementedError();
+  String get _serviceTypeName => throw new UnimplementedError();
+
+  Uint8List read(int len) {
+    if (len != null && len <= 0) {
+      throw new ArgumentError("Illegal length $len");
+    }
+    if (isClosing || isClosed) return null;
+    len = min(available, len == null ? available : len);
+    if (len == 0) return null;
+    var result = nativeRead(len);
+    if (result is OSError) {
+      reportError(result, StackTrace.current, "Read failed");
+      return null;
+    }
+    if (result != null) {
+      available -= result.length;
+      // TODO(ricow): Remove when we track internal and pipe uses.
+      assert(resourceInfo != null || isPipe || isInternal || isInternalSignal);
+      if (resourceInfo != null) {
+        resourceInfo.totalRead += result.length;
+      }
+    }
+    // TODO(ricow): Remove when we track internal and pipe uses.
+    assert(resourceInfo != null || isPipe || isInternal || isInternalSignal);
+    if (resourceInfo != null) {
+      resourceInfo.didRead();
+    }
+    return result;
+  }
+
+  Datagram receive() {
+    if (isClosing || isClosed) return null;
+    var result = nativeRecvFrom();
+    if (result is OSError) {
+      reportError(result, StackTrace.current, "Receive failed");
+      return null;
+    }
+    if (result != null) {
+      // Read the next available. Available is only for the next datagram, not
+      // the sum of all datagrams pending, so we need to call after each
+      // receive. If available becomes > 0, the _NativeSocket will continue to
+      // emit read events.
+      available = nativeAvailable();
+      // TODO(ricow): Remove when we track internal and pipe uses.
+      assert(resourceInfo != null || isPipe || isInternal || isInternalSignal);
+      if (resourceInfo != null) {
+        resourceInfo.totalRead += result.data.length;
+      }
+    }
+    // TODO(ricow): Remove when we track internal and pipe uses.
+    assert(resourceInfo != null || isPipe || isInternal || isInternalSignal);
+    if (resourceInfo != null) {
+      resourceInfo.didRead();
+    }
+    return result;
+  }
+
+  int write(List<int> buffer, int offset, int bytes) {
+    if (buffer is! List) throw new ArgumentError();
+    if (offset == null) offset = 0;
+    if (bytes == null) {
+      if (offset > buffer.length) {
+        throw new RangeError.value(offset);
+      }
+      bytes = buffer.length - offset;
+    }
+    if (offset < 0) throw new RangeError.value(offset);
+    if (bytes < 0) throw new RangeError.value(bytes);
+    if ((offset + bytes) > buffer.length) {
+      throw new RangeError.value(offset + bytes);
+    }
+    if (offset is! int || bytes is! int) {
+      throw new ArgumentError("Invalid arguments to write on Socket");
+    }
+    if (isClosing || isClosed) return 0;
+    if (bytes == 0) return 0;
+    _BufferAndStart bufferAndStart =
+        _ensureFastAndSerializableByteData(buffer, offset, offset + bytes);
+    var result =
+        nativeWrite(bufferAndStart.buffer, bufferAndStart.start, bytes);
+    if (result is OSError) {
+      OSError osError = result;
+      StackTrace st = StackTrace.current;
+      scheduleMicrotask(() => reportError(osError, st, "Write failed"));
+      result = 0;
+    }
+    // The result may be negative, if we forced a short write for testing
+    // purpose. In such case, don't mark writeAvailable as false, as we don't
+    // know if we'll receive an event. It's better to just retry.
+    if (result >= 0 && result < bytes) {
+      writeAvailable = false;
+    }
+    // Negate the result, as stated above.
+    if (result < 0) result = -result;
+    // TODO(ricow): Remove when we track internal and pipe uses.
+    assert(resourceInfo != null || isPipe || isInternal || isInternalSignal);
+    if (resourceInfo != null) {
+      resourceInfo.addWrite(result);
+    }
+    return result;
+  }
+
+  int send(List<int> buffer, int offset, int bytes, InternetAddress address,
+      int port) {
+    _throwOnBadPort(port);
+    if (isClosing || isClosed) return 0;
+    _BufferAndStart bufferAndStart =
+        _ensureFastAndSerializableByteData(buffer, offset, bytes);
+    var result = nativeSendTo(bufferAndStart.buffer, bufferAndStart.start,
+        bytes, (address as _InternetAddress)._in_addr, port);
+    if (result is OSError) {
+      OSError osError = result;
+      StackTrace st = StackTrace.current;
+      scheduleMicrotask(() => reportError(osError, st, "Send failed"));
+      result = 0;
+    }
+    // TODO(ricow): Remove when we track internal and pipe uses.
+    assert(resourceInfo != null || isPipe || isInternal || isInternalSignal);
+    if (resourceInfo != null) {
+      resourceInfo.addWrite(result);
+    }
+    return result;
+  }
+
+  _NativeSocket accept() {
+    // Don't issue accept if we're closing.
+    if (isClosing || isClosed) return null;
+    assert(available > 0);
+    available--;
+    tokens++;
+    returnTokens(listeningTokenBatchSize);
+    var socket = new _NativeSocket.normal();
+    if (nativeAccept(socket) != true) return null;
+    socket.localPort = localPort;
+    socket.localAddress = address;
+    setupResourceInfo(socket);
+    // TODO(ricow): Remove when we track internal and pipe uses.
+    assert(resourceInfo != null || isPipe || isInternal || isInternalSignal);
+    if (resourceInfo != null) {
+      // We track this as read one byte.
+      resourceInfo.addRead(1);
+    }
+    return socket;
+  }
+
+  int get port {
+    if (localPort != 0) return localPort;
+    if (isClosing || isClosed) throw const SocketException.closed();
+    var result = nativeGetPort();
+    if (result is OSError) throw result;
+    return localPort = result;
+  }
+
+  int get remotePort {
+    if (isClosing || isClosed) throw const SocketException.closed();
+    var result = nativeGetRemotePeer();
+    if (result is OSError) throw result;
+    return result[1];
+  }
+
+  InternetAddress get address => localAddress;
+
+  InternetAddress get remoteAddress {
+    if (isClosing || isClosed) throw const SocketException.closed();
+    var result = nativeGetRemotePeer();
+    if (result is OSError) throw result;
+    var addr = result[0];
+    var type = new InternetAddressType._from(addr[0]);
+    return new _InternetAddress(addr[1], null, addr[2]);
+  }
+
+  void issueReadEvent() {
+    if (closedReadEventSent) return;
+    if (readEventIssued) return;
+    readEventIssued = true;
+    void issue() {
+      readEventIssued = false;
+      if (isClosing) return;
+      if (!sendReadEvents) return;
+      if (available == 0) {
+        if (isClosedRead && !closedReadEventSent) {
+          if (isClosedWrite) close();
+          var handler = eventHandlers[closedEvent];
+          if (handler == null) return;
+          closedReadEventSent = true;
+          handler();
+        }
+        return;
+      }
+      var handler = eventHandlers[readEvent];
+      if (handler == null) return;
+      readEventIssued = true;
+      handler();
+      scheduleMicrotask(issue);
+    }
+
+    scheduleMicrotask(issue);
+  }
+
+  void issueWriteEvent({bool delayed: true}) {
+    if (writeEventIssued) return;
+    if (!writeAvailable) return;
+    void issue() {
+      writeEventIssued = false;
+      if (!writeAvailable) return;
+      if (isClosing) return;
+      if (!sendWriteEvents) return;
+      sendWriteEvents = false;
+      var handler = eventHandlers[writeEvent];
+      if (handler == null) return;
+      handler();
+    }
+
+    if (delayed) {
+      writeEventIssued = true;
+      scheduleMicrotask(issue);
+    } else {
+      issue();
+    }
+  }
+
+  // Multiplexes socket events to the socket handlers.
+  void multiplex(Object eventsObj) {
+    // TODO(paulberry): when issue #31305 is fixed, we should be able to simply
+    // declare `events` as a `covariant int` parameter.
+    int events = eventsObj;
+    for (int i = firstEvent; i <= lastEvent; i++) {
+      if (((events & (1 << i)) != 0)) {
+        if ((i == closedEvent || i == readEvent) && isClosedRead) continue;
+        if (isClosing && i != destroyedEvent) continue;
+        if (i == closedEvent && !isListening && !isClosing && !isClosed) {
+          isClosedRead = true;
+          issueReadEvent();
+          continue;
+        }
+
+        if (i == writeEvent) {
+          writeAvailable = true;
+          issueWriteEvent(delayed: false);
+          continue;
+        }
+
+        if (i == readEvent) {
+          if (isListening) {
+            available++;
+          } else {
+            available = nativeAvailable();
+            issueReadEvent();
+            continue;
+          }
+        }
+
+        var handler = eventHandlers[i];
+        if (i == destroyedEvent) {
+          assert(isClosing);
+          assert(!isClosed);
+          // TODO(ricow): Remove/update when we track internal and pipe uses.
+          assert(
+              resourceInfo != null || isPipe || isInternal || isInternalSignal);
+          if (resourceInfo != null) {
+            _SocketResourceInfo.SocketClosed(resourceInfo);
+          }
+          isClosed = true;
+          closeCompleter.complete();
+          disconnectFromEventHandler();
+          if (handler != null) handler();
+          continue;
+        }
+
+        if (i == errorEvent) {
+          if (!isClosing) {
+            reportError(nativeGetError(), null, "");
+          }
+        } else if (!isClosed) {
+          // If the connection is closed right after it's accepted, there's a
+          // chance the close-handler is not set.
+          if (handler != null) handler();
+        }
+      }
+    }
+    if (!isListening) {
+      tokens++;
+      returnTokens(normalTokenBatchSize);
+    }
+  }
+
+  void returnTokens(int tokenBatchSize) {
+    if (!isClosing && !isClosed) {
+      assert(eventPort != null);
+      // Return in batches.
+      if (tokens == tokenBatchSize) {
+        assert(tokens < (1 << firstCommand));
+        sendToEventHandler((1 << returnTokenCommand) | tokens);
+        tokens = 0;
+      }
+    }
+  }
+
+  void setHandlers({read, write, error, closed, destroyed}) {
+    eventHandlers[readEvent] = read;
+    eventHandlers[writeEvent] = write;
+    eventHandlers[errorEvent] = error;
+    eventHandlers[closedEvent] = closed;
+    eventHandlers[destroyedEvent] = destroyed;
+  }
+
+  void setListening({read: true, write: true}) {
+    sendReadEvents = read;
+    sendWriteEvents = write;
+    if (read) issueReadEvent();
+    if (write) issueWriteEvent();
+    if (!flagsSent && !isClosing) {
+      flagsSent = true;
+      int flags = 1 << setEventMaskCommand;
+      if (!isClosedRead) flags |= 1 << readEvent;
+      if (!isClosedWrite) flags |= 1 << writeEvent;
+      sendToEventHandler(flags);
+    }
+  }
+
+  Future close() {
+    if (!isClosing && !isClosed) {
+      sendToEventHandler(1 << closeCommand);
+      isClosing = true;
+    }
+    return closeCompleter.future;
+  }
+
+  void shutdown(SocketDirection direction) {
+    if (!isClosing && !isClosed) {
+      switch (direction) {
+        case SocketDirection.receive:
+          shutdownRead();
+          break;
+        case SocketDirection.send:
+          shutdownWrite();
+          break;
+        case SocketDirection.both:
+          close();
+          break;
+        default:
+          throw new ArgumentError(direction);
+      }
+    }
+  }
+
+  void shutdownWrite() {
+    if (!isClosing && !isClosed) {
+      if (closedReadEventSent) {
+        close();
+      } else {
+        sendToEventHandler(1 << shutdownWriteCommand);
+      }
+      isClosedWrite = true;
+    }
+  }
+
+  void shutdownRead() {
+    if (!isClosing && !isClosed) {
+      if (isClosedWrite) {
+        close();
+      } else {
+        sendToEventHandler(1 << shutdownReadCommand);
+      }
+      isClosedRead = true;
+    }
+  }
+
+  void sendToEventHandler(int data) {
+    int fullData = (typeFlags & typeTypeMask) | data;
+    assert(!isClosing);
+    connectToEventHandler();
+    _EventHandler._sendData(this, eventPort.sendPort, fullData);
+  }
+
+  void connectToEventHandler() {
+    assert(!isClosed);
+    if (eventPort == null) {
+      eventPort = new RawReceivePort(multiplex);
+    }
+    if (!connectedResourceHandler) {
+      registerExtension(
+          'ext.dart.io.getOpenSockets', _SocketResourceInfo.getOpenSockets);
+      registerExtension('ext.dart.io.getSocketByID',
+          _SocketResourceInfo.getSocketInfoMapByID);
+
+      connectedResourceHandler = true;
+    }
+  }
+
+  void disconnectFromEventHandler() {
+    assert(eventPort != null);
+    eventPort.close();
+    eventPort = null;
+    // Now that we don't track this Socket anymore, we can clear the owner
+    // field.
+    owner = null;
+  }
+
+  // Check whether this is an error response from a native port call.
+  static bool isErrorResponse(response) {
+    return response is List && response[0] != _successResponse;
+  }
+
+  // Create the appropriate error/exception from different returned
+  // error objects.
+  static createError(error, String message,
+      [InternetAddress address, int port]) {
+    if (error is OSError) {
+      return new SocketException(message,
+          osError: error, address: address, port: port);
+    } else if (error is List) {
+      assert(isErrorResponse(error));
+      switch (error[0]) {
+        case _illegalArgumentResponse:
+          return new ArgumentError();
+        case _osErrorResponse:
+          return new SocketException(message,
+              osError: new OSError(error[2], error[1]),
+              address: address,
+              port: port);
+        default:
+          return new Exception("Unknown error");
+      }
+    } else {
+      return new SocketException(message, address: address, port: port);
+    }
+  }
+
+  void reportError(error, StackTrace st, String message) {
+    var e = createError(error, message, address, localPort);
+    // Invoke the error handler if any.
+    if (eventHandlers[errorEvent] != null) {
+      eventHandlers[errorEvent](e, st);
+    }
+    // For all errors we close the socket
+    close();
+  }
+
+  getOption(SocketOption option) {
+    if (option == null) throw new ArgumentError.notNull("option");
+    var result = nativeGetOption(option._value, address.type._value);
+    if (result is OSError) throw result;
+    return result;
+  }
+
+  bool setOption(SocketOption option, value) {
+    if (option == null) throw new ArgumentError.notNull("option");
+    var result = nativeSetOption(option._value, address.type._value, value);
+    if (result != null) throw result;
+    return true;
+  }
+
+  Uint8List getRawOption(RawSocketOption option) {
+    if (option == null) throw new ArgumentError.notNull("option");
+    if (option.value == null) throw new ArgumentError.notNull("option.value");
+
+    var result = nativeGetRawOption(option.level, option.option, option.value);
+    if (result != null) throw result;
+    return option.value;
+  }
+
+  void setRawOption(RawSocketOption option) {
+    if (option == null) throw new ArgumentError.notNull("option");
+    if (option.value == null) throw new ArgumentError.notNull("option.value");
+
+    var result = nativeSetRawOption(option.level, option.option, option.value);
+    if (result != null) throw result;
+  }
+
+  InternetAddress multicastAddress(
+      InternetAddress addr, NetworkInterface interface) {
+    // On Mac OS using the interface index for joining IPv4 multicast groups
+    // is not supported. Here the IP address of the interface is needed.
+    if (Platform.isMacOS && addr.type == InternetAddressType.IPv4) {
+      if (interface != null) {
+        for (int i = 0; i < interface.addresses.length; i++) {
+          if (interface.addresses[i].type == InternetAddressType.IPv4) {
+            return interface.addresses[i];
+          }
+        }
+        // No IPv4 address found on the interface.
+        throw new SocketException(
+            "The network interface does not have an address "
+            "of the same family as the multicast address");
+      } else {
+        // Default to the ANY address if no interface is specified.
+        return InternetAddress.anyIPv4;
+      }
+    } else {
+      return null;
+    }
+  }
+
+  void joinMulticast(InternetAddress addr, NetworkInterface interface) {
+    _InternetAddress interfaceAddr = multicastAddress(addr, interface);
+    var interfaceIndex = interface == null ? 0 : interface.index;
+    var result = nativeJoinMulticast((addr as _InternetAddress)._in_addr,
+        interfaceAddr?._in_addr, interfaceIndex);
+    if (result is OSError) throw result;
+  }
+
+  void leaveMulticast(InternetAddress addr, NetworkInterface interface) {
+    _InternetAddress interfaceAddr = multicastAddress(addr, interface);
+    var interfaceIndex = interface == null ? 0 : interface.index;
+    var result = nativeLeaveMulticast((addr as _InternetAddress)._in_addr,
+        interfaceAddr?._in_addr, interfaceIndex);
+    if (result is OSError) throw result;
+  }
+
+  void nativeSetSocketId(int id, int typeFlags) native "Socket_SetSocketId";
+  nativeAvailable() native "Socket_Available";
+  nativeRead(int len) native "Socket_Read";
+  nativeRecvFrom() native "Socket_RecvFrom";
+  nativeWrite(List<int> buffer, int offset, int bytes)
+      native "Socket_WriteList";
+  nativeSendTo(List<int> buffer, int offset, int bytes, Uint8List address,
+      int port) native "Socket_SendTo";
+  nativeCreateConnect(Uint8List addr, int port, int scope_id)
+      native "Socket_CreateConnect";
+  nativeCreateBindConnect(Uint8List addr, int port, Uint8List sourceAddr,
+      int scope_id) native "Socket_CreateBindConnect";
+  bool isBindError(int errorNumber) native "SocketBase_IsBindError";
+  nativeCreateBindListen(Uint8List addr, int port, int backlog, bool v6Only,
+      bool shared, int scope_id) native "ServerSocket_CreateBindListen";
+  nativeCreateBindDatagram(Uint8List addr, int port, bool reuseAddress,
+      bool reusePort, int ttl) native "Socket_CreateBindDatagram";
+  nativeAccept(_NativeSocket socket) native "ServerSocket_Accept";
+  int nativeGetPort() native "Socket_GetPort";
+  List nativeGetRemotePeer() native "Socket_GetRemotePeer";
+  int nativeGetSocketId() native "Socket_GetSocketId";
+  OSError nativeGetError() native "Socket_GetError";
+  nativeGetOption(int option, int protocol) native "Socket_GetOption";
+  OSError nativeGetRawOption(int level, int option, Uint8List data)
+      native "Socket_GetRawOption";
+  OSError nativeSetOption(int option, int protocol, value)
+      native "Socket_SetOption";
+  OSError nativeSetRawOption(int level, int option, Uint8List data)
+      native "Socket_SetRawOption";
+  OSError nativeJoinMulticast(Uint8List addr, Uint8List interfaceAddr,
+      int interfaceIndex) native "Socket_JoinMulticast";
+  bool nativeLeaveMulticast(Uint8List addr, Uint8List interfaceAddr,
+      int interfaceIndex) native "Socket_LeaveMulticast";
+}
+
+class _RawServerSocket extends Stream<RawSocket> implements RawServerSocket {
+  final _NativeSocket _socket;
+  StreamController<RawSocket> _controller;
+  ReceivePort _referencePort;
+  bool _v6Only;
+
+  static Future<_RawServerSocket> bind(
+      address, int port, int backlog, bool v6Only, bool shared) {
+    _throwOnBadPort(port);
+    if (backlog < 0) throw new ArgumentError("Invalid backlog $backlog");
+    return _NativeSocket.bind(address, port, backlog, v6Only, shared)
+        .then((socket) => new _RawServerSocket(socket, v6Only));
+  }
+
+  _RawServerSocket(this._socket, this._v6Only);
+
+  StreamSubscription<RawSocket> listen(void onData(RawSocket event),
+      {Function onError, void onDone(), bool cancelOnError}) {
+    if (_controller != null) {
+      throw new StateError("Stream was already listened to");
+    }
+    var zone = Zone.current;
+    _controller = new StreamController(
+        sync: true,
+        onListen: _onSubscriptionStateChange,
+        onCancel: _onSubscriptionStateChange,
+        onPause: _onPauseStateChange,
+        onResume: _onPauseStateChange);
+    _socket.setHandlers(read: zone.bindCallbackGuarded(() {
+      while (_socket.available > 0) {
+        var socket = _socket.accept();
+        if (socket == null) return;
+        _controller.add(new _RawSocket(socket));
+        if (_controller.isPaused) return;
+      }
+    }), error: zone.bindBinaryCallbackGuarded((e, st) {
+      _controller.addError(e, st);
+      _controller.close();
+    }), destroyed: () {
+      _controller.close();
+      if (_referencePort != null) {
+        _referencePort.close();
+        _referencePort = null;
+      }
+    });
+    return _controller.stream.listen(onData,
+        onError: onError, onDone: onDone, cancelOnError: cancelOnError);
+  }
+
+  int get port => _socket.port;
+
+  InternetAddress get address => _socket.address;
+
+  Future<RawServerSocket> close() {
+    return _socket.close().then<RawServerSocket>((_) {
+      if (_referencePort != null) {
+        _referencePort.close();
+        _referencePort = null;
+      }
+      return this;
+    });
+  }
+
+  void _pause() {
+    _socket.setListening(read: false, write: false);
+  }
+
+  void _resume() {
+    _socket.setListening(read: true, write: false);
+  }
+
+  void _onSubscriptionStateChange() {
+    if (_controller.hasListener) {
+      _resume();
+    } else {
+      _socket.close();
+    }
+  }
+
+  void _onPauseStateChange() {
+    if (_controller.isPaused) {
+      _pause();
+    } else {
+      _resume();
+    }
+  }
+
+  void set _owner(owner) {
+    _socket.owner = owner;
+  }
+}
+
+class _RawSocket extends Stream<RawSocketEvent> implements RawSocket {
+  final _NativeSocket _socket;
+  StreamController<RawSocketEvent> _controller;
+  bool _readEventsEnabled = true;
+  bool _writeEventsEnabled = true;
+
+  // Flag to handle Ctrl-D closing of stdio on Mac OS.
+  bool _isMacOSTerminalInput = false;
+
+  static Future<RawSocket> connect(
+      host, int port, sourceAddress, Duration timeout) {
+    return _NativeSocket.connect(host, port, sourceAddress, timeout)
+        .then((socket) => new _RawSocket(socket));
+  }
+
+  static Future<ConnectionTask<_RawSocket>> startConnect(
+      host, int port, sourceAddress) {
+    return _NativeSocket.startConnect(host, port, sourceAddress)
+        .then((ConnectionTask<_NativeSocket> nativeTask) {
+      final Future<_RawSocket> raw = nativeTask.socket
+          .then((_NativeSocket nativeSocket) => new _RawSocket(nativeSocket));
+      return new ConnectionTask<_RawSocket>._(
+          socket: raw, onCancel: nativeTask._onCancel);
+    });
+  }
+
+  _RawSocket(this._socket) {
+    var zone = Zone.current;
+    _controller = new StreamController(
+        sync: true,
+        onListen: _onSubscriptionStateChange,
+        onCancel: _onSubscriptionStateChange,
+        onPause: _onPauseStateChange,
+        onResume: _onPauseStateChange);
+    _socket.setHandlers(
+        read: () => _controller.add(RawSocketEvent.read),
+        write: () {
+          // The write event handler is automatically disabled by the
+          // event handler when it fires.
+          writeEventsEnabled = false;
+          _controller.add(RawSocketEvent.write);
+        },
+        closed: () => _controller.add(RawSocketEvent.readClosed),
+        destroyed: () {
+          _controller.add(RawSocketEvent.closed);
+          _controller.close();
+        },
+        error: zone.bindBinaryCallbackGuarded((e, st) {
+          _controller.addError(e, st);
+          _socket.close();
+        }));
+  }
+
+  factory _RawSocket._writePipe() {
+    var native = new _NativeSocket.pipe();
+    native.isClosedRead = true;
+    native.closedReadEventSent = true;
+    return new _RawSocket(native);
+  }
+
+  factory _RawSocket._readPipe(int fd) {
+    var native = new _NativeSocket.pipe();
+    native.isClosedWrite = true;
+    if (fd != null) _getStdioHandle(native, fd);
+    var result = new _RawSocket(native);
+    if (fd != null) {
+      var socketType = _StdIOUtils._nativeSocketType(result._socket);
+      result._isMacOSTerminalInput =
+          Platform.isMacOS && socketType == _stdioHandleTypeTerminal;
+    }
+    return result;
+  }
+
+  StreamSubscription<RawSocketEvent> listen(void onData(RawSocketEvent event),
+      {Function onError, void onDone(), bool cancelOnError}) {
+    return _controller.stream.listen(onData,
+        onError: onError, onDone: onDone, cancelOnError: cancelOnError);
+  }
+
+  int available() => _socket.available;
+
+  Uint8List read([int len]) {
+    if (_isMacOSTerminalInput) {
+      var available = this.available();
+      if (available == 0) return null;
+      var data = _socket.read(len);
+      if (data == null || data.length < available) {
+        // Reading less than available from a Mac OS terminal indicate Ctrl-D.
+        // This is interpreted as read closed.
+        scheduleMicrotask(() => _controller.add(RawSocketEvent.readClosed));
+      }
+      return data;
+    } else {
+      return _socket.read(len);
+    }
+  }
+
+  int write(List<int> buffer, [int offset, int count]) =>
+      _socket.write(buffer, offset, count);
+
+  Future<RawSocket> close() => _socket.close().then<RawSocket>((_) => this);
+
+  void shutdown(SocketDirection direction) => _socket.shutdown(direction);
+
+  int get port => _socket.port;
+
+  int get remotePort => _socket.remotePort;
+
+  InternetAddress get address => _socket.address;
+
+  InternetAddress get remoteAddress => _socket.remoteAddress;
+
+  bool get readEventsEnabled => _readEventsEnabled;
+  void set readEventsEnabled(bool value) {
+    if (value != _readEventsEnabled) {
+      _readEventsEnabled = value;
+      if (!_controller.isPaused) _resume();
+    }
+  }
+
+  bool get writeEventsEnabled => _writeEventsEnabled;
+  void set writeEventsEnabled(bool value) {
+    if (value != _writeEventsEnabled) {
+      _writeEventsEnabled = value;
+      if (!_controller.isPaused) _resume();
+    }
+  }
+
+  bool setOption(SocketOption option, bool enabled) =>
+      _socket.setOption(option, enabled);
+
+  Uint8List getRawOption(RawSocketOption option) =>
+      _socket.getRawOption(option);
+  void setRawOption(RawSocketOption option) => _socket.setRawOption(option);
+
+  _pause() {
+    _socket.setListening(read: false, write: false);
+  }
+
+  void _resume() {
+    _socket.setListening(read: _readEventsEnabled, write: _writeEventsEnabled);
+  }
+
+  void _onPauseStateChange() {
+    if (_controller.isPaused) {
+      _pause();
+    } else {
+      _resume();
+    }
+  }
+
+  void _onSubscriptionStateChange() {
+    if (_controller.hasListener) {
+      _resume();
+    } else {
+      _socket.close();
+    }
+  }
+
+  void set _owner(owner) {
+    _socket.owner = owner;
+  }
+}
+
+@patch
+class ServerSocket {
+  @patch
+  static Future<ServerSocket> bind(address, int port,
+      {int backlog: 0, bool v6Only: false, bool shared: false}) {
+    return _ServerSocket.bind(address, port, backlog, v6Only, shared);
+  }
+}
+
+class _ServerSocket extends Stream<Socket> implements ServerSocket {
+  final _socket;
+
+  static Future<_ServerSocket> bind(
+      address, int port, int backlog, bool v6Only, bool shared) {
+    return _RawServerSocket.bind(address, port, backlog, v6Only, shared)
+        .then((socket) => new _ServerSocket(socket));
+  }
+
+  _ServerSocket(this._socket);
+
+  StreamSubscription<Socket> listen(void onData(Socket event),
+      {Function onError, void onDone(), bool cancelOnError}) {
+    return _socket.map<Socket>((rawSocket) => new _Socket(rawSocket)).listen(
+        onData,
+        onError: onError,
+        onDone: onDone,
+        cancelOnError: cancelOnError);
+  }
+
+  int get port => _socket.port;
+
+  InternetAddress get address => _socket.address;
+
+  Future<ServerSocket> close() =>
+      _socket.close().then<ServerSocket>((_) => this);
+
+  void set _owner(owner) {
+    _socket._owner = owner;
+  }
+}
+
+@patch
+class Socket {
+  @patch
+  static Future<Socket> _connect(host, int port,
+      {sourceAddress, Duration timeout}) {
+    return RawSocket.connect(host, port,
+            sourceAddress: sourceAddress, timeout: timeout)
+        .then((socket) => new _Socket(socket));
+  }
+
+  @patch
+  static Future<ConnectionTask<Socket>> _startConnect(host, int port,
+      {sourceAddress}) {
+    return RawSocket.startConnect(host, port, sourceAddress: sourceAddress)
+        .then((rawTask) {
+      Future<Socket> socket =
+          rawTask.socket.then((rawSocket) => new _Socket(rawSocket));
+      return new ConnectionTask<Socket>._(
+          socket: socket, onCancel: rawTask._onCancel);
+    });
+  }
+}
+
+class _SocketStreamConsumer extends StreamConsumer<List<int>> {
+  StreamSubscription subscription;
+  final _Socket socket;
+  int offset;
+  List<int> buffer;
+  bool paused = false;
+  Completer streamCompleter;
+
+  _SocketStreamConsumer(this.socket);
+
+  Future<Socket> addStream(Stream<List<int>> stream) {
+    socket._ensureRawSocketSubscription();
+    streamCompleter = new Completer<Socket>();
+    if (socket._raw != null) {
+      subscription = stream.listen((data) {
+        assert(!paused);
+        assert(buffer == null);
+        buffer = data;
+        offset = 0;
+        try {
+          write();
+        } catch (e) {
+          socket.destroy();
+          stop();
+          done(e);
+        }
+      }, onError: (error, [stackTrace]) {
+        socket.destroy();
+        done(error, stackTrace);
+      }, onDone: () {
+        done();
+      }, cancelOnError: true);
+    }
+    return streamCompleter.future;
+  }
+
+  Future<Socket> close() {
+    socket._consumerDone();
+    return new Future.value(socket);
+  }
+
+  void write() {
+    if (subscription == null) return;
+    assert(buffer != null);
+    // Write as much as possible.
+    offset += socket._write(buffer, offset, buffer.length - offset);
+    if (offset < buffer.length) {
+      if (!paused) {
+        paused = true;
+        subscription.pause();
+      }
+      socket._enableWriteEvent();
+    } else {
+      buffer = null;
+      if (paused) {
+        paused = false;
+        subscription.resume();
+      }
+    }
+  }
+
+  void done([error, stackTrace]) {
+    if (streamCompleter != null) {
+      if (error != null) {
+        streamCompleter.completeError(error, stackTrace);
+      } else {
+        streamCompleter.complete(socket);
+      }
+      streamCompleter = null;
+    }
+  }
+
+  void stop() {
+    if (subscription == null) return;
+    subscription.cancel();
+    subscription = null;
+    paused = false;
+    socket._disableWriteEvent();
+  }
+}
+
+class _Socket extends Stream<Uint8List> implements Socket {
+  RawSocket _raw; // Set to null when the raw socket is closed.
+  bool _closed = false; // Set to true when the raw socket is closed.
+  StreamController<Uint8List> _controller;
+  bool _controllerClosed = false;
+  _SocketStreamConsumer _consumer;
+  IOSink _sink;
+  var _subscription;
+  var _detachReady;
+
+  _Socket(this._raw) {
+    _controller = new StreamController<Uint8List>(
+        sync: true,
+        onListen: _onSubscriptionStateChange,
+        onCancel: _onSubscriptionStateChange,
+        onPause: _onPauseStateChange,
+        onResume: _onPauseStateChange);
+    _consumer = new _SocketStreamConsumer(this);
+    _sink = new IOSink(_consumer);
+
+    // Disable read events until there is a subscription.
+    _raw.readEventsEnabled = false;
+
+    // Disable write events until the consumer needs it for pending writes.
+    _raw.writeEventsEnabled = false;
+  }
+
+  factory _Socket._writePipe() {
+    return new _Socket(new _RawSocket._writePipe());
+  }
+
+  factory _Socket._readPipe([int fd]) {
+    return new _Socket(new _RawSocket._readPipe(fd));
+  }
+
+  // Note: this code seems a bit suspicious because _raw can be _RawSocket and
+  // it can be _RawSecureSocket because _SecureSocket extends _Socket
+  // and these two types are incompatible because _RawSecureSocket._socket
+  // is Socket and not _NativeSocket.
+  _NativeSocket get _nativeSocket => (_raw as _RawSocket)._socket;
+
+  StreamSubscription<Uint8List> listen(void onData(Uint8List event),
+      {Function onError, void onDone(), bool cancelOnError}) {
+    return _controller.stream.listen(onData,
+        onError: onError, onDone: onDone, cancelOnError: cancelOnError);
+  }
+
+  Encoding get encoding => _sink.encoding;
+
+  void set encoding(Encoding value) {
+    _sink.encoding = value;
+  }
+
+  void write(Object obj) => _sink.write(obj);
+
+  void writeln([Object obj = ""]) => _sink.writeln(obj);
+
+  void writeCharCode(int charCode) => _sink.writeCharCode(charCode);
+
+  void writeAll(Iterable objects, [sep = ""]) => _sink.writeAll(objects, sep);
+
+  void add(List<int> bytes) => _sink.add(bytes);
+
+  void addError(Object error, [StackTrace stackTrace]) {
+    throw new UnsupportedError("Cannot send errors on sockets");
+  }
+
+  Future addStream(Stream<List<int>> stream) {
+    return _sink.addStream(stream);
+  }
+
+  Future flush() => _sink.flush();
+
+  Future close() => _sink.close();
+
+  Future get done => _sink.done;
+
+  void destroy() {
+    // Destroy can always be called to get rid of a socket.
+    if (_raw == null) return;
+    _consumer.stop();
+    _closeRawSocket();
+    _controllerClosed = true;
+    _controller.close();
+  }
+
+  bool setOption(SocketOption option, bool enabled) {
+    if (_raw == null) return false;
+    return _raw.setOption(option, enabled);
+  }
+
+  Uint8List getRawOption(RawSocketOption option) {
+    if (_raw == null) return null;
+    return _raw.getRawOption(option);
+  }
+
+  void setRawOption(RawSocketOption option) {
+    _raw?.setRawOption(option);
+  }
+
+  int get port {
+    if (_raw == null) throw const SocketException.closed();
+    ;
+    return _raw.port;
+  }
+
+  InternetAddress get address {
+    if (_raw == null) throw const SocketException.closed();
+    ;
+    return _raw.address;
+  }
+
+  int get remotePort {
+    if (_raw == null) throw const SocketException.closed();
+    ;
+    return _raw.remotePort;
+  }
+
+  InternetAddress get remoteAddress {
+    if (_raw == null) throw const SocketException.closed();
+    ;
+    return _raw.remoteAddress;
+  }
+
+  Future _detachRaw() {
+    _detachReady = new Completer();
+    _sink.close();
+    return _detachReady.future.then((_) {
+      assert(_consumer.buffer == null);
+      var raw = _raw;
+      _raw = null;
+      return [raw, _subscription];
+    });
+  }
+
+  // Ensure a subscription on the raw socket. Both the stream and the
+  // consumer needs a subscription as they share the error and done
+  // events from the raw socket.
+  void _ensureRawSocketSubscription() {
+    if (_subscription == null && _raw != null) {
+      _subscription = _raw.listen(_onData,
+          onError: _onError, onDone: _onDone, cancelOnError: true);
+    }
+  }
+
+  _closeRawSocket() {
+    var tmp = _raw;
+    _raw = null;
+    _closed = true;
+    tmp.close();
+  }
+
+  void _onSubscriptionStateChange() {
+    if (_controller.hasListener) {
+      _ensureRawSocketSubscription();
+      // Enable read events for providing data to subscription.
+      if (_raw != null) {
+        _raw.readEventsEnabled = true;
+      }
+    } else {
+      _controllerClosed = true;
+      if (_raw != null) {
+        _raw.shutdown(SocketDirection.receive);
+      }
+    }
+  }
+
+  void _onPauseStateChange() {
+    if (_raw != null) {
+      _raw.readEventsEnabled = !_controller.isPaused;
+    }
+  }
+
+  void _onData(event) {
+    switch (event) {
+      case RawSocketEvent.read:
+        if (_raw == null) break;
+        var buffer = _raw.read();
+        if (buffer != null) _controller.add(buffer);
+        break;
+      case RawSocketEvent.write:
+        _consumer.write();
+        break;
+      case RawSocketEvent.readClosed:
+        _controllerClosed = true;
+        _controller.close();
+        break;
+    }
+  }
+
+  void _onDone() {
+    if (!_controllerClosed) {
+      _controllerClosed = true;
+      _controller.close();
+    }
+    _consumer.done();
+  }
+
+  void _onError(error, stackTrace) {
+    if (!_controllerClosed) {
+      _controllerClosed = true;
+      _controller.addError(error, stackTrace);
+      _controller.close();
+    }
+    _consumer.done(error, stackTrace);
+  }
+
+  int _write(List<int> data, int offset, int length) {
+    if (_raw != null) {
+      return _raw.write(data, offset, length);
+    }
+    return 0;
+  }
+
+  void _enableWriteEvent() {
+    if (_raw != null) {
+      _raw.writeEventsEnabled = true;
+    }
+  }
+
+  void _disableWriteEvent() {
+    if (_raw != null) {
+      _raw.writeEventsEnabled = false;
+    }
+  }
+
+  void _consumerDone() {
+    if (_detachReady != null) {
+      _detachReady.complete(null);
+    } else {
+      if (_raw != null) {
+        _raw.shutdown(SocketDirection.send);
+        _disableWriteEvent();
+      }
+    }
+  }
+
+  void set _owner(owner) {
+    // Note: _raw can be _RawSocket and _RawSecureSocket which are two
+    // incompatible types.
+    (_raw as dynamic)._owner = owner;
+  }
+}
+
+@patch
+class RawDatagramSocket {
+  @patch
+  static Future<RawDatagramSocket> bind(host, int port,
+      {bool reuseAddress: true, bool reusePort: false, int ttl: 1}) {
+    return _RawDatagramSocket.bind(host, port, reuseAddress, reusePort, ttl);
+  }
+}
+
+class _RawDatagramSocket extends Stream<RawSocketEvent>
+    implements RawDatagramSocket {
+  _NativeSocket _socket;
+  StreamController<RawSocketEvent> _controller;
+  bool _readEventsEnabled = true;
+  bool _writeEventsEnabled = true;
+
+  _RawDatagramSocket(this._socket) {
+    var zone = Zone.current;
+    _controller = new StreamController<RawSocketEvent>(
+        sync: true,
+        onListen: _onSubscriptionStateChange,
+        onCancel: _onSubscriptionStateChange,
+        onPause: _onPauseStateChange,
+        onResume: _onPauseStateChange);
+    _socket.setHandlers(
+        read: () => _controller.add(RawSocketEvent.read),
+        write: () {
+          // The write event handler is automatically disabled by the
+          // event handler when it fires.
+          writeEventsEnabled = false;
+          _controller.add(RawSocketEvent.write);
+        },
+        closed: () => _controller.add(RawSocketEvent.readClosed),
+        destroyed: () {
+          _controller.add(RawSocketEvent.closed);
+          _controller.close();
+        },
+        error: zone.bindBinaryCallbackGuarded((e, st) {
+          _controller.addError(e, st);
+          _socket.close();
+        }));
+  }
+
+  static Future<RawDatagramSocket> bind(
+      host, int port, bool reuseAddress, bool reusePort, int ttl) {
+    _throwOnBadPort(port);
+    _throwOnBadTtl(ttl);
+    return _NativeSocket.bindDatagram(host, port, reuseAddress, reusePort, ttl)
+        .then((socket) => new _RawDatagramSocket(socket));
+  }
+
+  StreamSubscription<RawSocketEvent> listen(void onData(RawSocketEvent event),
+      {Function onError, void onDone(), bool cancelOnError}) {
+    return _controller.stream.listen(onData,
+        onError: onError, onDone: onDone, cancelOnError: cancelOnError);
+  }
+
+  Future close() => _socket.close().then<RawDatagramSocket>((_) => this);
+
+  int send(List<int> buffer, InternetAddress address, int port) =>
+      _socket.send(buffer, 0, buffer.length, address, port);
+
+  Datagram receive() {
+    return _socket.receive();
+  }
+
+  void joinMulticast(InternetAddress group, [NetworkInterface interface]) {
+    _socket.joinMulticast(group, interface);
+  }
+
+  void leaveMulticast(InternetAddress group, [NetworkInterface interface]) {
+    _socket.leaveMulticast(group, interface);
+  }
+
+  bool get readEventsEnabled => _readEventsEnabled;
+  void set readEventsEnabled(bool value) {
+    if (value != _readEventsEnabled) {
+      _readEventsEnabled = value;
+      if (!_controller.isPaused) _resume();
+    }
+  }
+
+  bool get writeEventsEnabled => _writeEventsEnabled;
+  void set writeEventsEnabled(bool value) {
+    if (value != _writeEventsEnabled) {
+      _writeEventsEnabled = value;
+      if (!_controller.isPaused) _resume();
+    }
+  }
+
+  bool get multicastLoopback =>
+      _socket.getOption(SocketOption._ipMulticastLoop);
+  void set multicastLoopback(bool value) =>
+      _socket.setOption(SocketOption._ipMulticastLoop, value);
+
+  int get multicastHops => _socket.getOption(SocketOption._ipMulticastHops);
+  void set multicastHops(int value) =>
+      _socket.setOption(SocketOption._ipMulticastHops, value);
+
+  NetworkInterface get multicastInterface => throw "Not implemented";
+  void set multicastInterface(NetworkInterface value) =>
+      throw "Not implemented";
+
+  bool get broadcastEnabled => _socket.getOption(SocketOption._ipBroadcast);
+  void set broadcastEnabled(bool value) =>
+      _socket.setOption(SocketOption._ipBroadcast, value);
+
+  int get port => _socket.port;
+
+  InternetAddress get address => _socket.address;
+
+  _pause() {
+    _socket.setListening(read: false, write: false);
+  }
+
+  void _resume() {
+    _socket.setListening(read: _readEventsEnabled, write: _writeEventsEnabled);
+  }
+
+  void _onPauseStateChange() {
+    if (_controller.isPaused) {
+      _pause();
+    } else {
+      _resume();
+    }
+  }
+
+  void _onSubscriptionStateChange() {
+    if (_controller.hasListener) {
+      _resume();
+    } else {
+      _socket.close();
+    }
+  }
+
+  Uint8List getRawOption(RawSocketOption option) =>
+      _socket.getRawOption(option);
+  void setRawOption(RawSocketOption option) => _socket.setRawOption(option);
+}
+
+@pragma("vm:entry-point", "call")
+Datagram _makeDatagram(
+    Uint8List data, String address, Uint8List in_addr, int port) {
+  return new Datagram(data, new _InternetAddress(address, null, in_addr), port);
+}
diff --git a/sdk_nnbd/lib/_internal/vm/bin/stdio_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/stdio_patch.dart
new file mode 100644
index 0000000..58d1d0a
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/bin/stdio_patch.dart
@@ -0,0 +1,168 @@
+// 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 "common_patch.dart";
+
+@patch
+class _StdIOUtils {
+  @patch
+  static Stdin _getStdioInputStream(int fd) {
+    switch (_getStdioHandleType(fd)) {
+      case _stdioHandleTypeTerminal:
+      case _stdioHandleTypePipe:
+      case _stdioHandleTypeSocket:
+        return new Stdin._(new _Socket._readPipe(fd), fd);
+      case _stdioHandleTypeFile:
+        return new Stdin._(new _FileStream.forStdin(), fd);
+      default:
+        throw new FileSystemException(
+            "Couldn't determine file type of stdin (fd $fd)");
+    }
+  }
+
+  @patch
+  static _getStdioOutputStream(int fd) {
+    switch (_getStdioHandleType(fd)) {
+      case _stdioHandleTypeTerminal:
+      case _stdioHandleTypePipe:
+      case _stdioHandleTypeSocket:
+      case _stdioHandleTypeFile:
+        return new Stdout._(new IOSink(new _StdConsumer(fd)), fd);
+      default:
+        throw new FileSystemException(
+            "Couldn't determine file type of stdio handle (fd $fd)");
+    }
+  }
+
+  @patch
+  static int _socketType(Socket socket) {
+    if (socket is _Socket) return _nativeSocketType(socket._nativeSocket);
+    return null;
+  }
+
+  static int _nativeSocketType(_NativeSocket nativeSocket) {
+    var result = _getSocketType(nativeSocket);
+    if (result is OSError) {
+      throw new FileSystemException("Error retrieving socket type", "", result);
+    }
+    return result;
+  }
+
+  @patch
+  static _getStdioHandleType(int fd) native "File_GetStdioHandleType";
+}
+
+@patch
+class Stdin {
+  @patch
+  int readByteSync() {
+    var result = _readByte(_fd);
+    if (result is OSError) {
+      throw new StdinException("Error reading byte from stdin", result);
+    }
+    return result;
+  }
+
+  @patch
+  bool get echoMode {
+    var result = _echoMode(_fd);
+    if (result is OSError) {
+      throw new StdinException("Error getting terminal echo mode", result);
+    }
+    return result;
+  }
+
+  @patch
+  void set echoMode(bool enabled) {
+    if (!_EmbedderConfig._maySetEchoMode) {
+      throw new UnsupportedError(
+          "This embedder disallows setting Stdin.echoMode");
+    }
+    var result = _setEchoMode(_fd, enabled);
+    if (result is OSError) {
+      throw new StdinException("Error setting terminal echo mode", result);
+    }
+  }
+
+  @patch
+  bool get lineMode {
+    var result = _lineMode(_fd);
+    if (result is OSError) {
+      throw new StdinException("Error getting terminal line mode", result);
+    }
+    return result;
+  }
+
+  @patch
+  void set lineMode(bool enabled) {
+    if (!_EmbedderConfig._maySetLineMode) {
+      throw new UnsupportedError(
+          "This embedder disallows setting Stdin.lineMode");
+    }
+    var result = _setLineMode(_fd, enabled);
+    if (result is OSError) {
+      throw new StdinException("Error setting terminal line mode", result);
+    }
+  }
+
+  @patch
+  bool get supportsAnsiEscapes {
+    var result = _supportsAnsiEscapes(_fd);
+    if (result is OSError) {
+      throw new StdinException("Error determining ANSI support", result);
+    }
+    return result;
+  }
+
+  static _echoMode(int fd) native "Stdin_GetEchoMode";
+  static _setEchoMode(int fd, bool enabled) native "Stdin_SetEchoMode";
+  static _lineMode(int fd) native "Stdin_GetLineMode";
+  static _setLineMode(int fd, bool enabled) native "Stdin_SetLineMode";
+  static _readByte(int fd) native "Stdin_ReadByte";
+  static _supportsAnsiEscapes(int fd) native "Stdin_AnsiSupported";
+}
+
+@patch
+class Stdout {
+  @patch
+  bool _hasTerminal(int fd) {
+    try {
+      _terminalSize(fd);
+      return true;
+    } catch (_) {
+      return false;
+    }
+  }
+
+  @patch
+  int _terminalColumns(int fd) => _terminalSize(fd)[0];
+  @patch
+  int _terminalLines(int fd) => _terminalSize(fd)[1];
+
+  static List _terminalSize(int fd) {
+    var size = _getTerminalSize(fd);
+    if (size is! List) {
+      throw new StdoutException("Could not get terminal size", size);
+    }
+    return size;
+  }
+
+  static _getTerminalSize(int fd) native "Stdout_GetTerminalSize";
+
+  @patch
+  static bool _supportsAnsiEscapes(int fd) {
+    var result = _getAnsiSupported(fd);
+    if (result is! bool) {
+      throw new StdoutException("Error determining ANSI support", result);
+    }
+    return result;
+  }
+
+  static _getAnsiSupported(int fd) native "Stdout_AnsiSupported";
+}
+
+_getStdioHandle(_NativeSocket socket, int num) native "Socket_GetStdioHandle";
+_getSocketType(_NativeSocket nativeSocket) native "Socket_GetType";
diff --git a/sdk_nnbd/lib/_internal/vm/bin/sync_socket_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/sync_socket_patch.dart
new file mode 100644
index 0000000..941aba4
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/bin/sync_socket_patch.dart
@@ -0,0 +1,351 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "common_patch.dart";
+
+@patch
+class RawSynchronousSocket {
+  @patch
+  static RawSynchronousSocket connectSync(host, int port) {
+    return _RawSynchronousSocket.connectSync(host, port);
+  }
+}
+
+class _RawSynchronousSocket implements RawSynchronousSocket {
+  final _NativeSynchronousSocket _socket;
+
+  _RawSynchronousSocket(this._socket);
+
+  static RawSynchronousSocket connectSync(host, int port) {
+    _throwOnBadPort(port);
+    return new _RawSynchronousSocket(
+        _NativeSynchronousSocket.connectSync(host, port));
+  }
+
+  InternetAddress get address => _socket.address;
+  int get port => _socket.port;
+  InternetAddress get remoteAddress => _socket.remoteAddress;
+  int get remotePort => _socket.remotePort;
+
+  int available() => _socket.available;
+
+  void closeSync() => _socket.closeSync();
+
+  int readIntoSync(List<int> buffer, [int start = 0, int end]) =>
+      _socket.readIntoSync(buffer, start, end);
+
+  List<int> readSync(int bytes) => _socket.readSync(bytes);
+
+  void shutdown(SocketDirection direction) => _socket.shutdown(direction);
+
+  void writeFromSync(List<int> buffer, [int start = 0, int end]) =>
+      _socket.writeFromSync(buffer, start, end);
+}
+
+// The NativeFieldWrapperClass1 can not be used with a mixin, due to missing
+// implicit constructor.
+class _NativeSynchronousSocketNativeWrapper extends NativeFieldWrapperClass1 {}
+
+// The _NativeSynchronousSocket class encapsulates a synchronous OS socket.
+class _NativeSynchronousSocket extends _NativeSynchronousSocketNativeWrapper {
+  // Socket close state.
+  bool isClosed = false;
+  bool isClosedRead = false;
+  bool isClosedWrite = false;
+
+  // Holds the address used to connect the socket.
+  InternetAddress localAddress;
+
+  // Holds the port of the socket, 0 if not known.
+  int localPort = 0;
+
+  _ReadWriteResourceInfo resourceInfo;
+
+  static _NativeSynchronousSocket connectSync(host, int port) {
+    if (host == null) {
+      throw new ArgumentError("Parameter host cannot be null");
+    }
+    List<_InternetAddress> addresses = null;
+    var error = null;
+    if (host is _InternetAddress) {
+      addresses = [host];
+    } else {
+      try {
+        addresses = lookup(host);
+      } catch (e) {
+        error = e;
+      }
+      if (error != null || addresses == null || addresses.isEmpty) {
+        throw createError(error, "Failed host lookup: '$host'");
+      }
+    }
+    assert(addresses is List);
+    var it = addresses.iterator;
+    _NativeSynchronousSocket connectNext() {
+      if (!it.moveNext()) {
+        // Could not connect. Throw the first connection error we encountered.
+        assert(error != null);
+        throw error;
+      }
+      var address = it.current;
+      var socket = new _NativeSynchronousSocket();
+      socket.localAddress = address;
+      var result = socket._nativeCreateConnectSync(address._in_addr, port);
+      if (result is OSError) {
+        // Keep first error, if present.
+        if (error == null) {
+          error = createError(result, "Connection failed", address, port);
+        }
+        return connectNext();
+      } else {
+        // Query the local port, for error messages.
+        try {
+          socket.port;
+        } catch (e) {
+          if (error == null) {
+            error = createError(e, "Connection failed", address, port);
+          }
+          return connectNext();
+        }
+        setupResourceInfo(socket);
+      }
+      return socket;
+    }
+
+    return connectNext();
+  }
+
+  InternetAddress get address => localAddress;
+  int get available => _nativeAvailable();
+
+  int get port {
+    if (localPort != 0) {
+      return localPort;
+    }
+    if (isClosed) {
+      throw const SocketException.closed();
+    }
+    var result = _nativeGetPort();
+    if (result is OSError) {
+      throw result;
+    }
+    return localPort = result;
+  }
+
+  InternetAddress get remoteAddress {
+    if (isClosed) {
+      throw const SocketException.closed();
+    }
+    var result = _nativeGetRemotePeer();
+    if (result is OSError) {
+      throw result;
+    }
+    var addr = result[0];
+    return new _InternetAddress(addr[1], null, addr[2]);
+  }
+
+  int get remotePort {
+    if (isClosed) {
+      throw const SocketException.closed();
+    }
+    var result = _nativeGetRemotePeer();
+    if (result is OSError) {
+      throw result;
+    }
+    return result[1];
+  }
+
+  void closeSync() {
+    if (!isClosed) {
+      _nativeCloseSync();
+      _SocketResourceInfo.SocketClosed(resourceInfo);
+      isClosed = true;
+    }
+  }
+
+  // Create the appropriate error/exception from different returned
+  // error objects.
+  static createError(error, String message,
+      [InternetAddress address, int port]) {
+    if (error is OSError) {
+      return new SocketException(message,
+          osError: error, address: address, port: port);
+    } else {
+      return new SocketException(message, address: address, port: port);
+    }
+  }
+
+  static List<_InternetAddress> lookup(String host,
+      {InternetAddressType type: InternetAddressType.ANY}) {
+    var response = _nativeLookupRequest(host, type._value);
+    if (response is OSError) {
+      throw response;
+    }
+    List<_InternetAddress> addresses =
+        new List<_InternetAddress>(response.length);
+    for (int i = 0; i < response.length; ++i) {
+      var result = response[i];
+      addresses[i] = new _InternetAddress(result[1], host, result[2]);
+    }
+    return addresses;
+  }
+
+  int readIntoSync(List<int> buffer, int start, int end) {
+    _checkAvailable();
+    if (isClosedRead) {
+      throw new SocketException("Socket is closed for reading");
+    }
+
+    if ((buffer is! List) ||
+        ((start != null) && (start is! int)) ||
+        ((end != null) && (end is! int))) {
+      throw new ArgumentError("Invalid arguments to readIntoSync");
+    }
+    if (start == null) {
+      throw new ArgumentError("start cannot be null");
+    }
+    end = RangeError.checkValidRange(start, end, buffer.length);
+    if (end == start) {
+      return 0;
+    }
+    var result = _nativeReadInto(buffer, start, (end - start));
+    if (result is OSError) {
+      throw new SocketException("readIntoSync failed", osError: result);
+    }
+    resourceInfo.addRead(result);
+    return result;
+  }
+
+  List<int> readSync(int len) {
+    _checkAvailable();
+    if (isClosedRead) {
+      throw new SocketException("Socket is closed for reading");
+    }
+
+    if ((len != null) && (len < 0)) {
+      throw new ArgumentError("Illegal length $len");
+    }
+    if (len == 0) {
+      return null;
+    }
+    var result = _nativeRead(len);
+    if (result is OSError) {
+      throw result;
+    }
+    assert(resourceInfo != null);
+    if (result != null) {
+      if (resourceInfo != null) {
+        resourceInfo.totalRead += result.length;
+      }
+    }
+    if (resourceInfo != null) {
+      resourceInfo.didRead();
+    }
+    return result;
+  }
+
+  static void setupResourceInfo(_NativeSynchronousSocket socket) {
+    socket.resourceInfo = new _SocketResourceInfo(socket);
+  }
+
+  void shutdown(SocketDirection direction) {
+    if (isClosed) {
+      return;
+    }
+    switch (direction) {
+      case SocketDirection.receive:
+        shutdownRead();
+        break;
+      case SocketDirection.send:
+        shutdownWrite();
+        break;
+      case SocketDirection.both:
+        closeSync();
+        break;
+      default:
+        throw new ArgumentError(direction);
+    }
+  }
+
+  void shutdownRead() {
+    if (isClosed || isClosedRead) {
+      return;
+    }
+    if (isClosedWrite) {
+      closeSync();
+    } else {
+      _nativeShutdownRead();
+    }
+    isClosedRead = true;
+  }
+
+  void shutdownWrite() {
+    if (isClosed || isClosedWrite) {
+      return;
+    }
+    if (isClosedRead) {
+      closeSync();
+    } else {
+      _nativeShutdownWrite();
+    }
+    isClosedWrite = true;
+  }
+
+  void writeFromSync(List<int> buffer, int start, int end) {
+    _checkAvailable();
+    if (isClosedWrite) {
+      throw new SocketException("Socket is closed for writing");
+    }
+    if ((buffer is! List) ||
+        ((start != null) && (start is! int)) ||
+        ((end != null) && (end is! int))) {
+      throw new ArgumentError("Invalid arguments to writeFromSync");
+    }
+    if (start == null) {
+      throw new ArgumentError("start cannot be equal to null");
+    }
+
+    end = RangeError.checkValidRange(start, end, buffer.length);
+    if (end == start) {
+      return;
+    }
+
+    _BufferAndStart bufferAndStart =
+        _ensureFastAndSerializableByteData(buffer, start, end);
+    var result = _nativeWrite(bufferAndStart.buffer, bufferAndStart.start,
+        end - (start - bufferAndStart.start));
+    if (result is OSError) {
+      throw new SocketException("writeFromSync failed", osError: result);
+    }
+    assert(resourceInfo != null);
+    if (resourceInfo != null) {
+      resourceInfo.addWrite(result);
+    }
+  }
+
+  void _checkAvailable() {
+    if (isClosed) {
+      throw const SocketException.closed();
+    }
+  }
+
+  // Native method declarations.
+  static _nativeLookupRequest(host, int type)
+      native "SynchronousSocket_LookupRequest";
+  _nativeCreateConnectSync(host, int port)
+      native "SynchronousSocket_CreateConnectSync";
+  _nativeAvailable() native "SynchronousSocket_Available";
+  _nativeCloseSync() native "SynchronousSocket_CloseSync";
+  int _nativeGetPort() native "SynchronousSocket_GetPort";
+  List _nativeGetRemotePeer() native "SynchronousSocket_GetRemotePeer";
+  _nativeRead(int len) native "SynchronousSocket_Read";
+  _nativeReadInto(List<int> buffer, int offset, int bytes)
+      native "SynchronousSocket_ReadList";
+  _nativeShutdownRead() native "SynchronousSocket_ShutdownRead";
+  _nativeShutdownWrite() native "SynchronousSocket_ShutdownWrite";
+  _nativeWrite(List<int> buffer, int offset, int bytes)
+      native "SynchronousSocket_WriteList";
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/array.dart b/sdk_nnbd/lib/_internal/vm/lib/array.dart
new file mode 100644
index 0000000..8113024
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/array.dart
@@ -0,0 +1,260 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+@pragma("vm:entry-point")
+class _List<E> extends FixedLengthListBase<E> {
+  @pragma("vm:exact-result-type", _List)
+  @pragma("vm:prefer-inline")
+  factory _List(length) native "List_allocate";
+
+  E operator [](int index) native "List_getIndexed";
+
+  void operator []=(int index, E value) {
+    _setIndexed(index, value);
+  }
+
+  void _setIndexed(int index, E value) native "List_setIndexed";
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  @pragma("vm:prefer-inline")
+  int get length native "List_getLength";
+
+  @pragma("vm:prefer-inline")
+  List _slice(int start, int count, bool needsTypeArgument) {
+    if (count <= 64) {
+      final result = needsTypeArgument ? new _List<E>(count) : new _List(count);
+      for (int i = 0; i < result.length; i++) {
+        result[i] = this[start + i];
+      }
+      return result;
+    } else {
+      return _sliceInternal(start, count, needsTypeArgument);
+    }
+  }
+
+  List _sliceInternal(int start, int count, bool needsTypeArgument)
+      native "List_slice";
+
+  // List interface.
+  void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
+    if (start < 0 || start > this.length) {
+      throw new RangeError.range(start, 0, this.length);
+    }
+    if (end < start || end > this.length) {
+      throw new RangeError.range(end, start, this.length);
+    }
+    int length = end - start;
+    if (length == 0) return;
+    if (identical(this, iterable)) {
+      Lists.copy(this, skipCount, this, start, length);
+    } else if (ClassID.getID(iterable) == ClassID.cidArray) {
+      final _List<E> iterableAsList = iterable;
+      Lists.copy(iterableAsList, skipCount, this, start, length);
+    } else if (iterable is List<E>) {
+      Lists.copy(iterable, skipCount, this, start, length);
+    } else {
+      Iterator it = iterable.iterator;
+      while (skipCount > 0) {
+        if (!it.moveNext()) return;
+        skipCount--;
+      }
+      for (int i = start; i < end; i++) {
+        if (!it.moveNext()) return;
+        this[i] = it.current;
+      }
+    }
+  }
+
+  void setAll(int index, Iterable<E> iterable) {
+    if (index < 0 || index > this.length) {
+      throw new RangeError.range(index, 0, this.length, "index");
+    }
+    List<E> iterableAsList;
+    if (identical(this, iterable)) {
+      iterableAsList = this;
+    } else if (ClassID.getID(iterable) == ClassID.cidArray) {
+      iterableAsList = iterable;
+    } else if (iterable is List<E>) {
+      iterableAsList = iterable;
+    } else {
+      for (var value in iterable) {
+        this[index++] = value;
+      }
+      return;
+    }
+    int length = iterableAsList.length;
+    if (index + length > this.length) {
+      throw new RangeError.range(index + length, 0, this.length);
+    }
+    Lists.copy(iterableAsList, 0, this, index, length);
+  }
+
+  List<E> sublist(int start, [int end]) {
+    end = RangeError.checkValidRange(start, end, this.length);
+    int length = end - start;
+    if (length == 0) return <E>[];
+    var result = new _GrowableList<E>._withData(_slice(start, length, false));
+    result._setLength(length);
+    return result;
+  }
+
+  // Iterable interface.
+
+  @pragma("vm:prefer-inline")
+  void forEach(f(E element)) {
+    final length = this.length;
+    for (int i = 0; i < length; i++) {
+      f(this[i]);
+    }
+  }
+
+  @pragma("vm:prefer-inline")
+  Iterator<E> get iterator {
+    return new _FixedSizeArrayIterator<E>(this);
+  }
+
+  E get first {
+    if (length > 0) return this[0];
+    throw IterableElementError.noElement();
+  }
+
+  E get last {
+    if (length > 0) return this[length - 1];
+    throw IterableElementError.noElement();
+  }
+
+  E get single {
+    if (length == 1) return this[0];
+    if (length == 0) throw IterableElementError.noElement();
+    throw IterableElementError.tooMany();
+  }
+
+  List<E> toList({bool growable: true}) {
+    var length = this.length;
+    if (length > 0) {
+      var result = _slice(0, length, !growable);
+      if (growable) {
+        result = new _GrowableList<E>._withData(result).._setLength(length);
+      }
+      return result;
+    }
+    // _GrowableList._withData must not be called with empty list.
+    return growable ? <E>[] : new List<E>(0);
+  }
+}
+
+// This is essentially the same class as _List, but it does not
+// permit any modification of array elements from Dart code. We use
+// this class for arrays constructed from Dart array literals.
+// TODO(hausner): We should consider the trade-offs between two
+// classes (and inline cache misses) versus a field in the native
+// implementation (checks when modifying). We should keep watching
+// the inline cache misses.
+@pragma("vm:entry-point")
+class _ImmutableList<E> extends UnmodifiableListBase<E> {
+  factory _ImmutableList._uninstantiable() {
+    throw new UnsupportedError(
+        "ImmutableArray can only be allocated by the VM");
+  }
+
+  factory _ImmutableList._from(List from, int offset, int length)
+      native "ImmutableList_from";
+
+  E operator [](int index) native "List_getIndexed";
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  @pragma("vm:prefer-inline")
+  int get length native "List_getLength";
+
+  List<E> sublist(int start, [int end]) {
+    end = RangeError.checkValidRange(start, end, this.length);
+    int length = end - start;
+    if (length == 0) return <E>[];
+    List list = new _List(length);
+    for (int i = 0; i < length; i++) {
+      list[i] = this[start + i];
+    }
+    var result = new _GrowableList<E>._withData(list);
+    result._setLength(length);
+    return result;
+  }
+
+  // Collection interface.
+
+  @pragma("vm:prefer-inline")
+  void forEach(f(E element)) {
+    final length = this.length;
+    for (int i = 0; i < length; i++) {
+      f(this[i]);
+    }
+  }
+
+  @pragma("vm:prefer-inline")
+  Iterator<E> get iterator {
+    return new _FixedSizeArrayIterator<E>(this);
+  }
+
+  E get first {
+    if (length > 0) return this[0];
+    throw IterableElementError.noElement();
+  }
+
+  E get last {
+    if (length > 0) return this[length - 1];
+    throw IterableElementError.noElement();
+  }
+
+  E get single {
+    if (length == 1) return this[0];
+    if (length == 0) throw IterableElementError.noElement();
+    throw IterableElementError.tooMany();
+  }
+
+  List<E> toList({bool growable: true}) {
+    var length = this.length;
+    if (length > 0) {
+      List list = growable ? new _List(length) : new _List<E>(length);
+      for (int i = 0; i < length; i++) {
+        list[i] = this[i];
+      }
+      if (!growable) return list;
+      var result = new _GrowableList<E>._withData(list);
+      result._setLength(length);
+      return result;
+    }
+    return growable ? <E>[] : new _List<E>(0);
+  }
+}
+
+// Iterator for arrays with fixed size.
+class _FixedSizeArrayIterator<E> implements Iterator<E> {
+  final List<E> _array;
+  final int _length; // Cache array length for faster access.
+  int _index;
+  E _current;
+
+  _FixedSizeArrayIterator(List<E> array)
+      : _array = array,
+        _length = array.length,
+        _index = 0 {
+    assert(array is _List<E> || array is _ImmutableList<E>);
+  }
+
+  E get current => _current;
+
+  @pragma("vm:prefer-inline")
+  bool moveNext() {
+    if (_index >= _length) {
+      _current = null;
+      return false;
+    }
+    _current = _array[_index];
+    _index++;
+    return true;
+  }
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/array_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/array_patch.dart
new file mode 100644
index 0000000..4c39149
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/array_patch.dart
@@ -0,0 +1,79 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+@patch
+class List<E> {
+  @patch
+  factory List([int length]) native "List_new";
+
+  @patch
+  factory List.filled(int length, E fill, {bool growable: false}) {
+    // All error handling on the length parameter is done at the implementation
+    // of new _List.
+    var result = growable ? new _GrowableList<E>(length) : new _List<E>(length);
+    if (fill != null) {
+      for (int i = 0; i < length; i++) {
+        result[i] = fill;
+      }
+    }
+    return result;
+  }
+
+  @patch
+  factory List.from(Iterable elements, {bool growable: true}) {
+    if (elements is EfficientLengthIterable<E>) {
+      int length = elements.length;
+      var list = growable ? new _GrowableList<E>(length) : new _List<E>(length);
+      if (length > 0) {
+        // Avoid creating iterator unless necessary.
+        int i = 0;
+        for (var element in elements) {
+          list[i++] = element;
+        }
+      }
+      return list;
+    }
+    // If elements is an Iterable<E>, we won't need a type-test for each
+    // element. In the "common case" that elements is an Iterable<E>, this
+    // replaces a type-test on every element with a single type-test before
+    // starting the loop.
+    if (elements is Iterable<E>) {
+      List<E> list = new _GrowableList<E>(0);
+      for (E e in elements) {
+        list.add(e);
+      }
+      if (growable) return list;
+      return makeListFixedLength(list);
+    } else {
+      List<E> list = new _GrowableList<E>(0);
+      for (E e in elements) {
+        list.add(e);
+      }
+      if (growable) return list;
+      return makeListFixedLength(list);
+    }
+  }
+
+  @patch
+  factory List.unmodifiable(Iterable elements) {
+    final result = new List<E>.from(elements, growable: false);
+    return makeFixedListUnmodifiable(result);
+  }
+
+  // Factory constructing a mutable List from a parser generated List literal.
+  // [elements] contains elements that are already type checked.
+  @pragma("vm:entry-point", "call")
+  factory List._fromLiteral(List elements) {
+    if (elements.isEmpty) {
+      return new _GrowableList<E>(0);
+    }
+    var result = new _GrowableList<E>._withData(elements);
+    result._setLength(elements.length);
+    return result;
+  }
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/async_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/async_patch.dart
new file mode 100644
index 0000000..f51fa04
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/async_patch.dart
@@ -0,0 +1,313 @@
+// 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.
+
+// @dart = 2.5
+
+/// Note: the VM concatenates all patch files into a single patch file. This
+/// file is the first patch in "dart:async" which contains all the imports used
+/// by patches of that library. We plan to change this when we have a shared
+/// front end and simply use parts.
+
+import "dart:_internal" show VMLibraryHooks, patch;
+
+/// These are the additional parts of this patch library:
+// part "deferred_load_patch.dart";
+// part "schedule_microtask_patch.dart";
+// part "timer_patch.dart";
+
+// Equivalent of calling FATAL from C++ code.
+_fatal(msg) native "DartAsync_fatal";
+
+class _AsyncAwaitCompleter<T> implements Completer<T> {
+  final _future = new _Future<T>();
+  bool isSync;
+
+  _AsyncAwaitCompleter() : isSync = false;
+
+  void complete([FutureOr<T> value]) {
+    if (!isSync || value is Future<T>) {
+      _future._asyncComplete(value);
+    } else {
+      _future._completeWithValue(value);
+    }
+  }
+
+  void completeError(e, [st]) {
+    if (isSync) {
+      _future._completeError(e, st);
+    } else {
+      _future._asyncCompleteError(e, st);
+    }
+  }
+
+  void start(f) {
+    f();
+    isSync = true;
+  }
+
+  Future<T> get future => _future;
+  bool get isCompleted => !_future._mayComplete;
+}
+
+// We need to pass the value as first argument and leave the second and third
+// arguments empty (used for error handling).
+// See vm/ast_transformer.cc for usage.
+Function _asyncThenWrapperHelper(continuation) {
+  // Any function that is used as an asynchronous callback must be registered
+  // in the current Zone. Normally, this is done by the future when a
+  // callback is registered (for example with `.then` or `.catchError`). In our
+  // case we want to reuse the same callback multiple times and therefore avoid
+  // the multiple registrations. For our internal futures (`_Future`) we can
+  // use the shortcut-version of `.then`, and skip the registration. However,
+  // that means that the continuation must be registered by us.
+  //
+  // Furthermore, we know that the root-zone doesn't actually do anything and
+  // we can therefore skip the registration call for it.
+  //
+  // Note, that the continuation accepts up to three arguments. If the current
+  // zone is the root zone, we don't wrap the continuation, and a bad
+  // `Future` implementation could potentially invoke the callback with the
+  // wrong number of arguments.
+  if (Zone.current == Zone.root) return continuation;
+  return Zone.current.registerUnaryCallback((x) => continuation(x, null, null));
+}
+
+// We need to pass the exception and stack trace objects as second and third
+// parameter to the continuation.  See vm/ast_transformer.cc for usage.
+Function _asyncErrorWrapperHelper(continuation) {
+  // See comments of `_asyncThenWrapperHelper`.
+  var errorCallback = (e, s) => continuation(null, e, s);
+  if (Zone.current == Zone.root) return errorCallback;
+  return Zone.current.registerBinaryCallback(errorCallback);
+}
+
+/// Registers the [thenCallback] and [errorCallback] on the given [object].
+///
+/// If [object] is not a future, then it is wrapped into one.
+///
+/// Returns the result of registering with `.then`.
+Future _awaitHelper(
+    var object, Function thenCallback, Function errorCallback, var awaiter) {
+  if (object is! Future) {
+    object = new _Future().._setValue(object);
+  } else if (object is! _Future) {
+    return object.then(thenCallback, onError: errorCallback);
+  }
+  // `object` is a `_Future`.
+  //
+  // Since the callbacks have been registered in the current zone (see
+  // [_asyncThenWrapperHelper] and [_asyncErrorWrapperHelper]), we can avoid
+  // another registration and directly invoke the no-zone-registration `.then`.
+  //
+  // We can only do this for our internal futures (the default implementation of
+  // all futures that are constructed by the `dart:async` library).
+  object._awaiter = awaiter;
+  return object._thenAwait(thenCallback, errorCallback);
+}
+
+// Called as part of the 'await for (...)' construct. Registers the
+// awaiter on the stream.
+void _asyncStarListenHelper(var object, var awaiter) {
+  if (object is! _StreamImpl) {
+    return;
+  }
+  // `object` is a `_StreamImpl`.
+  object._awaiter = awaiter;
+}
+
+@pragma("vm:entry-point", "call")
+void _asyncStarMoveNextHelper(var stream) {
+  if (stream is! _StreamImpl) {
+    return;
+  }
+  // stream is a _StreamImpl.
+  if (stream._generator == null) {
+    // No generator registered, this isn't an async* Stream.
+    return;
+  }
+  _moveNextDebuggerStepCheck(stream._generator);
+}
+
+// _AsyncStarStreamController is used by the compiler to implement
+// async* generator functions.
+@pragma("vm:entry-point")
+class _AsyncStarStreamController<T> {
+  StreamController<T> controller;
+  Function asyncStarBody;
+  bool isAdding = false;
+  bool onListenReceived = false;
+  bool isScheduled = false;
+  bool isSuspendedAtYield = false;
+  _Future cancellationFuture = null;
+
+  Stream<T> get stream {
+    final Stream<T> local = controller.stream;
+    if (local is _StreamImpl<T>) {
+      local._generator = asyncStarBody;
+    }
+    return local;
+  }
+
+  void runBody() {
+    isScheduled = false;
+    isSuspendedAtYield = false;
+    asyncStarBody();
+  }
+
+  void scheduleGenerator() {
+    if (isScheduled || controller.isPaused || isAdding) {
+      return;
+    }
+    isScheduled = true;
+    scheduleMicrotask(runBody);
+  }
+
+  // Adds element to stream, returns true if the caller should terminate
+  // execution of the generator.
+  //
+  // TODO(hausner): Per spec, the generator should be suspended before
+  // exiting when the stream is closed. We could add a getter like this:
+  // get isCancelled => controller.hasListener;
+  // The generator would translate a 'yield e' statement to
+  // controller.add(e);
+  // suspend;
+  // if (controller.isCancelled) return;
+  bool add(T event) {
+    if (!onListenReceived) _fatal("yield before stream is listened to");
+    if (isSuspendedAtYield) _fatal("unexpected yield");
+    // If stream is cancelled, tell caller to exit the async generator.
+    if (!controller.hasListener) {
+      return true;
+    }
+    controller.add(event);
+    scheduleGenerator();
+    isSuspendedAtYield = true;
+    return false;
+  }
+
+  // Adds the elements of stream into this controller's stream.
+  // The generator will be scheduled again when all of the
+  // elements of the added stream have been consumed.
+  // Returns true if the caller should terminate
+  // execution of the generator.
+  bool addStream(Stream<T> stream) {
+    if (!onListenReceived) _fatal("yield before stream is listened to");
+    // If stream is cancelled, tell caller to exit the async generator.
+    if (!controller.hasListener) return true;
+    isAdding = true;
+    var whenDoneAdding = controller.addStream(stream, cancelOnError: false);
+    whenDoneAdding.then((_) {
+      isAdding = false;
+      scheduleGenerator();
+      if (!isScheduled) isSuspendedAtYield = true;
+    });
+    return false;
+  }
+
+  void addError(Object error, StackTrace stackTrace) {
+    if ((cancellationFuture != null) && cancellationFuture._mayComplete) {
+      // If the stream has been cancelled, complete the cancellation future
+      // with the error.
+      cancellationFuture._completeError(error, stackTrace);
+      return;
+    }
+    // If stream is cancelled, tell caller to exit the async generator.
+    if (!controller.hasListener) return;
+    controller.addError(error, stackTrace);
+    // No need to schedule the generator body here. This code is only
+    // called from the catch clause of the implicit try-catch-finally
+    // around the generator body. That is, we are on the error path out
+    // of the generator and do not need to run the generator again.
+  }
+
+  close() {
+    if ((cancellationFuture != null) && cancellationFuture._mayComplete) {
+      // If the stream has been cancelled, complete the cancellation future
+      // with the error.
+      cancellationFuture._completeWithValue(null);
+    }
+    controller.close();
+  }
+
+  _AsyncStarStreamController(this.asyncStarBody) {
+    controller = new StreamController(
+        onListen: this.onListen,
+        onResume: this.onResume,
+        onCancel: this.onCancel);
+  }
+
+  onListen() {
+    assert(!onListenReceived);
+    onListenReceived = true;
+    scheduleGenerator();
+  }
+
+  onResume() {
+    if (isSuspendedAtYield) {
+      scheduleGenerator();
+    }
+  }
+
+  onCancel() {
+    if (controller.isClosed) {
+      return null;
+    }
+    if (cancellationFuture == null) {
+      cancellationFuture = new _Future();
+      // Only resume the generator if it is suspended at a yield.
+      // Cancellation does not affect an async generator that is
+      // suspended at an await.
+      if (isSuspendedAtYield) {
+        scheduleGenerator();
+      }
+    }
+    return cancellationFuture;
+  }
+}
+
+@patch
+void _rethrow(Object error, StackTrace stackTrace) native "Async_rethrow";
+
+@patch
+class _Future<T> {
+  /// The closure implementing the async[*]-body that is `await`ing this future.
+  Function _awaiter;
+}
+
+@patch
+class _StreamImpl<T> {
+  /// The closure implementing the async[*]-body that is `await`ing this future.
+  Function _awaiter;
+
+  /// The closure implementing the async-generator body that is creating events
+  /// for this stream.
+  Function _generator;
+}
+
+@pragma("vm:entry-point", "call")
+void _completeOnAsyncReturn(Completer completer, Object value) {
+  completer.complete(value);
+}
+
+/// Returns a [StackTrace] object containing the synchronous prefix for this
+/// asynchronous method.
+//
+// This method is recognized. It performs a runtime call if
+// FLAG_causal_async_stacks is enabled or returns `null` otherwise.
+@pragma("vm:prefer-inline")
+Object _asyncStackTraceHelper(Function async_op)
+    native "StackTrace_asyncStackTraceHelper";
+
+// This method is asm intrinsified.
+@pragma("vm:entry-point", "call")
+void _clearAsyncThreadStackTrace()
+    native "StackTrace_clearAsyncThreadStackTrace";
+
+// This method is asm intrinsified.
+@pragma("vm:entry-point", "call")
+void _setAsyncThreadStackTrace(StackTrace stackTrace)
+    native "StackTrace_setAsyncThreadStackTrace";
+
+void _moveNextDebuggerStepCheck(Function async_op)
+    native "AsyncStarMoveNext_debuggerStepCheck";
diff --git a/sdk_nnbd/lib/_internal/vm/lib/bigint_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/bigint_patch.dart
new file mode 100644
index 0000000..1730be8
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/bigint_patch.dart
@@ -0,0 +1,2812 @@
+// 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.
+
+// @dart = 2.5
+
+// part of dart.core;
+
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+ * Copyright (c) 2003-2005  Tom Wu
+ * Copyright (c) 2012 Adam Singer (adam@solvr.io)
+ * 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" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following condition applies:
+ *
+ * All redistributions must retain an intact copy of this copyright notice
+ * and disclaimer.
+ */
+
+@patch
+class BigInt implements Comparable<BigInt> {
+  @patch
+  static BigInt get zero => _BigIntImpl.zero;
+  @patch
+  static BigInt get one => _BigIntImpl.one;
+  @patch
+  static BigInt get two => _BigIntImpl.two;
+
+  @patch
+  static BigInt parse(String source, {int radix}) =>
+      _BigIntImpl.parse(source, radix: radix);
+
+  @patch
+  static BigInt tryParse(String source, {int radix}) =>
+      _BigIntImpl._tryParse(source, radix: radix);
+
+  @patch
+  factory BigInt.from(num value) => new _BigIntImpl.from(value);
+}
+
+int _max(int a, int b) => a > b ? a : b;
+int _min(int a, int b) => a < b ? a : b;
+
+/// Allocate a new digits list of even length.
+Uint32List _newDigits(int length) => new Uint32List(length + (length & 1));
+
+/**
+ * An implementation for the arbitrarily large integer.
+ *
+ * The integer number is represented by a sign, an array of 32-bit unsigned
+ * integers in little endian format, and a number of used digits in that array.
+ */
+class _BigIntImpl implements BigInt {
+  // Bits per digit.
+  static const int _digitBits = 32;
+  static const int _digitBase = 1 << _digitBits;
+  static const int _digitMask = (1 << _digitBits) - 1;
+
+  // Bits per half digit.
+  static const int _halfDigitBits = _digitBits >> 1;
+  static const int _halfDigitMask = (1 << _halfDigitBits) - 1;
+
+  static final _BigIntImpl zero = new _BigIntImpl._fromInt(0);
+  static final _BigIntImpl one = new _BigIntImpl._fromInt(1);
+  static final _BigIntImpl two = new _BigIntImpl._fromInt(2);
+
+  static final _BigIntImpl _minusOne = -one;
+  static final _BigIntImpl _oneDigitMask = new _BigIntImpl._fromInt(_digitMask);
+  static final _BigIntImpl _twoDigitMask = (one << (2 * _digitBits)) - one;
+  static final _BigIntImpl _oneBillion = new _BigIntImpl._fromInt(1000000000);
+  static const int _minInt = -0x8000000000000000;
+  static const int _maxInt = 0x7fffffffffffffff;
+
+  // Result cache for last _divRem call.
+  // Result cache for last _divRem call.
+  static Uint32List _lastDividendDigits;
+  static int _lastDividendUsed;
+  static Uint32List _lastDivisorDigits;
+  static int _lastDivisorUsed;
+  static Uint32List _lastQuoRemDigits;
+  static int _lastQuoRemUsed;
+  static int _lastRemUsed;
+  static int _lastRem_nsh;
+
+  /// Whether this bigint is negative.
+  final bool _isNegative;
+
+  /// The unsigned digits of this bigint.
+  ///
+  /// The least significant digit is in slot 0.
+  /// The list may have more digits than needed. That is, `_digits.length` may
+  /// be strictly greater than `_used`.
+  /// Also, `_digits.length` must always be even, because intrinsics on 64-bit
+  /// platforms may process a digit pair as a 64-bit value.
+  final Uint32List _digits;
+
+  /// The number of used entries in [_digits].
+  ///
+  /// To avoid reallocating [Uint32List]s, lists that are too big are not
+  /// replaced, but `_used` reflects the smaller number of digits actually used.
+  ///
+  /// Note that functions shortening an existing list of digits to a smaller
+  /// `_used` number of digits must ensure that the highermost pair of digits
+  /// is correct when read as a 64-bit value by intrinsics. Therefore, if the
+  /// smaller '_used' number is odd, the high digit of that pair must be
+  /// explicitly cleared, i.e. _digits[_used] = 0, which cannot result in an
+  /// out of bounds access, since the length of the list is guaranteed to be
+  /// even.
+  final int _used;
+
+  /**
+   * Parses [source] as a, possibly signed, integer literal and returns its
+   * value.
+   *
+   * The [source] must be a non-empty sequence of base-[radix] digits,
+   * optionally prefixed with a minus or plus sign ('-' or '+').
+   *
+   * The [radix] must be in the range 2..36. The digits used are
+   * first the decimal digits 0..9, and then the letters 'a'..'z' with
+   * values 10 through 35. Also accepts upper-case letters with the same
+   * values as the lower-case ones.
+   *
+   * If no [radix] is given then it defaults to 10. In this case, the [source]
+   * digits may also start with `0x`, in which case the number is interpreted
+   * as a hexadecimal literal, which effectively means that the `0x` is ignored
+   * and the radix is instead set to 16.
+   *
+   * For any int `n` and radix `r`, it is guaranteed that
+   * `n == int.parse(n.toRadixString(r), radix: r)`.
+   *
+   * Throws a [FormatException] if the [source] is not a valid integer literal,
+   * optionally prefixed by a sign.
+   */
+  static _BigIntImpl parse(String source, {int radix}) {
+    var result = _tryParse(source, radix: radix);
+    if (result == null) {
+      throw new FormatException("Could not parse BigInt", source);
+    }
+    return result;
+  }
+
+  /// Parses a decimal bigint literal.
+  ///
+  /// The [source] must not contain leading or trailing whitespace.
+  static _BigIntImpl _parseDecimal(String source, bool isNegative) {
+    const _0 = 48;
+
+    int part = 0;
+    _BigIntImpl result = zero;
+    // Read in the source 9 digits at a time.
+    // The first part may have a few leading virtual '0's to make the remaining
+    // parts all have exactly 9 digits.
+    int digitInPartCount = 9 - source.length.remainder(9);
+    if (digitInPartCount == 9) digitInPartCount = 0;
+    for (int i = 0; i < source.length; i++) {
+      part = part * 10 + source.codeUnitAt(i) - _0;
+      if (++digitInPartCount == 9) {
+        result = result * _oneBillion + new _BigIntImpl._fromInt(part);
+        part = 0;
+        digitInPartCount = 0;
+      }
+    }
+    if (isNegative) return -result;
+    return result;
+  }
+
+  /// Returns the value of a given source digit.
+  ///
+  /// Source digits between "0" and "9" (inclusive) return their decimal value.
+  ///
+  /// Source digits between "a" and "z", or "A" and "Z" (inclusive) return
+  /// 10 + their position in the ASCII alphabet.
+  ///
+  /// The incoming [codeUnit] must be an ASCII code-unit.
+  static int _codeUnitToRadixValue(int codeUnit) {
+    // We know that the characters must be ASCII as otherwise the
+    // regexp wouldn't have matched. Lowercasing by doing `| 0x20` is thus
+    // guaranteed to be a safe operation, since it preserves digits
+    // and lower-cases ASCII letters.
+    const int _0 = 48;
+    const int _9 = 57;
+    const int _a = 97;
+    if (_0 <= codeUnit && codeUnit <= _9) return codeUnit - _0;
+    codeUnit |= 0x20;
+    var result = codeUnit - _a + 10;
+    return result;
+  }
+
+  /// Parses the given [source] string, starting at [startPos], as a hex
+  /// literal.
+  ///
+  /// If [isNegative] is true, negates the result before returning it.
+  ///
+  /// The [source] (substring) must be a valid hex literal.
+  static _BigIntImpl _parseHex(String source, int startPos, bool isNegative) {
+    int hexCharsPerDigit = _digitBits ~/ 4;
+    int sourceLength = source.length - startPos;
+    int used = (sourceLength + hexCharsPerDigit - 1) ~/ hexCharsPerDigit;
+    var digits = _newDigits(used);
+
+    int lastDigitLength = sourceLength - (used - 1) * hexCharsPerDigit;
+    int digitIndex = used - 1;
+    int i = startPos;
+    int digit = 0;
+    for (int j = 0; j < lastDigitLength; j++) {
+      var value = _codeUnitToRadixValue(source.codeUnitAt(i++));
+      if (value >= 16) return null;
+      digit = digit * 16 + value;
+    }
+    digits[digitIndex--] = digit;
+
+    while (i < source.length) {
+      digit = 0;
+      for (int j = 0; j < hexCharsPerDigit; j++) {
+        var value = _codeUnitToRadixValue(source.codeUnitAt(i++));
+        if (value >= 16) return null;
+        digit = digit * 16 + value;
+      }
+      digits[digitIndex--] = digit;
+    }
+    if (used == 1 && digits[0] == 0) return zero;
+    return new _BigIntImpl._(isNegative, used, digits);
+  }
+
+  /// Parses the given [source] as a [radix] literal.
+  ///
+  /// The [source] will be checked for invalid characters. If it is invalid,
+  /// this function returns `null`.
+  static _BigIntImpl _parseRadix(String source, int radix, bool isNegative) {
+    var result = zero;
+    var base = new _BigIntImpl._fromInt(radix);
+    for (int i = 0; i < source.length; i++) {
+      var value = _codeUnitToRadixValue(source.codeUnitAt(i));
+      if (value >= radix) return null;
+      result = result * base + new _BigIntImpl._fromInt(value);
+    }
+    if (isNegative) return -result;
+    return result;
+  }
+
+  /// Tries to parse the given [source] as a [radix] literal.
+  ///
+  /// 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}) {
+    if (source == "") return null;
+
+    var re = new RegExp(r'^\s*([+-]?)((0x[a-f0-9]+)|(\d+)|([a-z0-9]+))\s*$',
+        caseSensitive: false);
+    var match = re.firstMatch(source);
+    int signIndex = 1;
+    int hexIndex = 3;
+    int decimalIndex = 4;
+    int nonDecimalHexIndex = 5;
+    if (match == null) return null;
+
+    bool isNegative = match[signIndex] == "-";
+
+    String decimalMatch = match[decimalIndex];
+    String hexMatch = match[hexIndex];
+    String nonDecimalMatch = match[nonDecimalHexIndex];
+
+    if (radix == null) {
+      if (decimalMatch != null) {
+        // Cannot fail because we know that the digits are all decimal.
+        return _parseDecimal(decimalMatch, isNegative);
+      }
+      if (hexMatch != null) {
+        // Cannot fail because we know that the digits are all hex.
+        return _parseHex(hexMatch, 2, isNegative);
+      }
+      return null;
+    }
+
+    if (radix is! int) {
+      throw new ArgumentError.value(radix, 'radix', 'is not an integer');
+    }
+    if (radix < 2 || radix > 36) {
+      throw new RangeError.range(radix, 2, 36, 'radix');
+    }
+    if (radix == 10 && decimalMatch != null) {
+      return _parseDecimal(decimalMatch, isNegative);
+    }
+    if (radix == 16 && (decimalMatch != null || nonDecimalMatch != null)) {
+      return _parseHex(decimalMatch ?? nonDecimalMatch, 0, isNegative);
+    }
+
+    return _parseRadix(
+        decimalMatch ?? nonDecimalMatch ?? hexMatch, radix, isNegative);
+  }
+
+  /// Finds the amount significant digits in the provided [digits] array.
+  static int _normalize(int used, Uint32List digits) {
+    while (used > 0 && digits[used - 1] == 0) used--;
+    return used;
+  }
+
+  /// Factory returning an instance initialized with the given field values.
+  /// If the [digits] array contains leading 0s, the [used] value is adjusted
+  /// accordingly. The [digits] array is not modified.
+  _BigIntImpl._(bool isNegative, int used, Uint32List digits)
+      : this._normalized(isNegative, _normalize(used, digits), digits);
+
+  _BigIntImpl._normalized(bool isNegative, this._used, this._digits)
+      : _isNegative = _used == 0 ? false : isNegative {
+    assert(_digits.length.isEven);
+    assert(_used.isEven || _digits[_used] == 0); // Leading zero for 64-bit.
+  }
+
+  /// Whether this big integer is zero.
+  bool get _isZero => _used == 0;
+
+  /// Allocates an array of the given [length] and copies the [digits] in the
+  /// range [from] to [to-1], starting at index 0, followed by leading zero
+  /// digits.
+  static Uint32List _cloneDigits(
+      Uint32List digits, int from, int to, int length) {
+    var resultDigits = _newDigits(length);
+    var n = to - from;
+    for (var i = 0; i < n; i++) {
+      resultDigits[i] = digits[from + i];
+    }
+    return resultDigits;
+  }
+
+  /// Allocates a big integer from the provided [value] number.
+  factory _BigIntImpl.from(num value) {
+    if (value == 0) return zero;
+    if (value == 1) return one;
+    if (value == 2) return two;
+
+    if (value.abs() < 0x100000000)
+      return new _BigIntImpl._fromInt(value.toInt());
+    if (value is double) return new _BigIntImpl._fromDouble(value);
+    return new _BigIntImpl._fromInt(value);
+  }
+
+  factory _BigIntImpl._fromInt(int value) {
+    bool isNegative = value < 0;
+    assert(_digitBits == 32);
+    var digits = _newDigits(2);
+    if (isNegative) {
+      // Handle the min 64-bit value differently, since its negation is not
+      // positive.
+      if (value == _minInt) {
+        digits[1] = 0x80000000;
+        return new _BigIntImpl._(true, 2, digits);
+      }
+      value = -value;
+    }
+    if (value < _digitBase) {
+      digits[0] = value;
+      return new _BigIntImpl._(isNegative, 1, digits);
+    }
+    digits[0] = value & _digitMask;
+    digits[1] = value >> _digitBits;
+    return new _BigIntImpl._(isNegative, 2, digits);
+  }
+
+  /// An 8-byte Uint8List we can reuse for [_fromDouble] to avoid generating
+  /// garbage.
+  static final Uint8List _bitsForFromDouble = new Uint8List(8);
+
+  factory _BigIntImpl._fromDouble(double value) {
+    const int exponentBias = 1075;
+
+    if (value.isNaN || value.isInfinite) {
+      throw new ArgumentError("Value must be finite: $value");
+    }
+    bool isNegative = value < 0;
+    if (isNegative) value = -value;
+
+    value = value.floorToDouble();
+    if (value == 0) return zero;
+
+    var bits = _bitsForFromDouble;
+    for (int i = 0; i < 8; i++) {
+      bits[i] = 0;
+    }
+    bits.buffer.asByteData().setFloat64(0, value, Endian.little);
+    // The exponent is in bits 53..63.
+    var biasedExponent = (bits[7] << 4) + (bits[6] >> 4);
+    var exponent = biasedExponent - exponentBias;
+
+    assert(_digitBits == 32);
+    // The significant bits are in 0 .. 52.
+    var unshiftedDigits = _newDigits(2);
+    unshiftedDigits[0] =
+        (bits[3] << 24) + (bits[2] << 16) + (bits[1] << 8) + bits[0];
+    // Don't forget to add the hidden bit.
+    unshiftedDigits[1] =
+        ((0x10 | (bits[6] & 0xF)) << 16) + (bits[5] << 8) + bits[4];
+
+    var unshiftedBig = new _BigIntImpl._normalized(false, 2, unshiftedDigits);
+    _BigIntImpl absResult = unshiftedBig;
+    if (exponent < 0) {
+      absResult = unshiftedBig >> -exponent;
+    } else if (exponent > 0) {
+      absResult = unshiftedBig << exponent;
+    }
+    if (isNegative) return -absResult;
+    return absResult;
+  }
+
+  /**
+   * Return the negative value of this integer.
+   *
+   * The result of negating an integer always has the opposite sign, except
+   * for zero, which is its own negation.
+   */
+  _BigIntImpl operator -() {
+    if (_used == 0) return this;
+    return new _BigIntImpl._(!_isNegative, _used, _digits);
+  }
+
+  /**
+   * Returns the absolute value of this integer.
+   *
+   * For any integer `x`, the result is the same as `x < 0 ? -x : x`.
+   */
+  _BigIntImpl abs() => _isNegative ? -this : this;
+
+  /// Returns this << n*_digitBits.
+  _BigIntImpl _dlShift(int n) {
+    final used = _used;
+    if (used == 0) {
+      return zero;
+    }
+    final resultUsed = used + n;
+    final digits = _digits;
+    final resultDigits = _newDigits(resultUsed);
+    for (int i = used - 1; i >= 0; i--) {
+      resultDigits[i + n] = digits[i];
+    }
+    return new _BigIntImpl._(_isNegative, resultUsed, resultDigits);
+  }
+
+  /// Same as [_dlShift] but works on the decomposed big integers.
+  ///
+  /// Returns `resultUsed`.
+  ///
+  /// `resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] << n*_digitBits`.
+  static int _dlShiftDigits(
+      Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
+    if (xUsed == 0) {
+      return 0;
+    }
+    if (n == 0 && identical(resultDigits, xDigits)) {
+      return xUsed;
+    }
+    final resultUsed = xUsed + n;
+    assert(resultDigits.length >= resultUsed + (resultUsed & 1));
+    for (int i = xUsed - 1; i >= 0; i--) {
+      resultDigits[i + n] = xDigits[i];
+    }
+    for (int i = n - 1; i >= 0; i--) {
+      resultDigits[i] = 0;
+    }
+    if (resultUsed.isOdd) {
+      resultDigits[resultUsed] = 0;
+    }
+    return resultUsed;
+  }
+
+  /// Returns `this >> n*_digitBits`.
+  _BigIntImpl _drShift(int n) {
+    final used = _used;
+    if (used == 0) {
+      return zero;
+    }
+    final resultUsed = used - n;
+    if (resultUsed <= 0) {
+      return _isNegative ? _minusOne : zero;
+    }
+    final digits = _digits;
+    final resultDigits = _newDigits(resultUsed);
+    for (var i = n; i < used; i++) {
+      resultDigits[i - n] = digits[i];
+    }
+    final result = new _BigIntImpl._(_isNegative, resultUsed, resultDigits);
+    if (_isNegative) {
+      // Round down if any bit was shifted out.
+      for (var i = 0; i < n; i++) {
+        if (digits[i] != 0) {
+          return result - one;
+        }
+      }
+    }
+    return result;
+  }
+
+  /// Same as [_drShift] but works on the decomposed big integers.
+  ///
+  /// Returns `resultUsed`.
+  ///
+  /// `resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] >> n*_digitBits`.
+  static int _drShiftDigits(
+      Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
+    final resultUsed = xUsed - n;
+    if (resultUsed <= 0) {
+      return 0;
+    }
+    assert(resultDigits.length >= resultUsed + (resultUsed & 1));
+    for (var i = n; i < xUsed; i++) {
+      resultDigits[i - n] = xDigits[i];
+    }
+    if (resultUsed.isOdd) {
+      resultDigits[resultUsed] = 0;
+    }
+    return resultUsed;
+  }
+
+  /// Shifts the digits of [xDigits] into the right place in [resultDigits].
+  ///
+  /// `resultDigits[ds..xUsed+ds] = xDigits[0..xUsed-1] << (n % _digitBits)`
+  ///   where `ds = n ~/ _digitBits`
+  ///
+  /// Does *not* clear digits below ds.
+  ///
+  /// Note: This function may be intrinsified.
+  @pragma("vm:never-inline")
+  static void _lsh(
+      Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
+    assert(xUsed > 0);
+    final digitShift = n ~/ _digitBits;
+    final bitShift = n % _digitBits;
+    final carryBitShift = _digitBits - bitShift;
+    final bitMask = (1 << carryBitShift) - 1;
+    var carry = 0;
+    for (int i = xUsed - 1; i >= 0; i--) {
+      final digit = xDigits[i];
+      resultDigits[i + digitShift + 1] = (digit >> carryBitShift) | carry;
+      carry = (digit & bitMask) << bitShift;
+    }
+    resultDigits[digitShift] = carry;
+  }
+
+  /**
+   * Shift the bits of this integer to the left by [shiftAmount].
+   *
+   * Shifting to the left makes the number larger, effectively multiplying
+   * the number by `pow(2, shiftIndex)`.
+   *
+   * There is no limit on the size of the result. It may be relevant to
+   * limit intermediate values by using the "and" operator with a suitable
+   * mask.
+   *
+   * It is an error if [shiftAmount] is negative.
+   */
+  _BigIntImpl operator <<(int shiftAmount) {
+    if (shiftAmount < 0) {
+      throw new ArgumentError("shift-amount must be positive $shiftAmount");
+    }
+    if (_isZero) return this;
+    final digitShift = shiftAmount ~/ _digitBits;
+    final bitShift = shiftAmount % _digitBits;
+    if (bitShift == 0) {
+      return _dlShift(digitShift);
+    }
+    // Need one extra digit to hold bits shifted by bitShift.
+    var resultUsed = _used + digitShift + 1;
+    // The 64-bit intrinsic requires one extra pair to work with.
+    var resultDigits = _newDigits(resultUsed + 1);
+    _lsh(_digits, _used, shiftAmount, resultDigits);
+    return new _BigIntImpl._(_isNegative, resultUsed, resultDigits);
+  }
+
+  /// resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] << n.
+  /// Returns resultUsed.
+  static int _lShiftDigits(
+      Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
+    final digitsShift = n ~/ _digitBits;
+    final bitShift = n % _digitBits;
+    if (bitShift == 0) {
+      return _dlShiftDigits(xDigits, xUsed, digitsShift, resultDigits);
+    }
+    // Need one extra digit to hold bits shifted by bitShift.
+    var resultUsed = xUsed + digitsShift + 1;
+    // The 64-bit intrinsic requires one extra pair to work with.
+    assert(resultDigits.length >= resultUsed + 2 - (resultUsed & 1));
+    _lsh(xDigits, xUsed, n, resultDigits);
+    var i = digitsShift;
+    while (--i >= 0) {
+      resultDigits[i] = 0;
+    }
+    if (resultDigits[resultUsed - 1] == 0) {
+      resultUsed--; // Clamp result.
+    } else if (resultUsed.isOdd) {
+      resultDigits[resultUsed] = 0;
+    }
+    return resultUsed;
+  }
+
+  /// resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] >> n.
+  ///
+  /// Note: This function may be intrinsified.
+  @pragma("vm:never-inline")
+  static void _rsh(
+      Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
+    assert(xUsed > 0);
+    final digitsShift = n ~/ _digitBits;
+    final bitShift = n % _digitBits;
+    final carryBitShift = _digitBits - bitShift;
+    final bitMask = (1 << bitShift) - 1;
+    var carry = xDigits[digitsShift] >> bitShift;
+    final last = xUsed - digitsShift - 1;
+    for (var i = 0; i < last; i++) {
+      final digit = xDigits[i + digitsShift + 1];
+      resultDigits[i] = ((digit & bitMask) << carryBitShift) | carry;
+      carry = digit >> bitShift;
+    }
+    resultDigits[last] = carry;
+  }
+
+  /**
+   * Shift the bits of this integer to the right by [shiftAmount].
+   *
+   * Shifting to the right makes the number smaller and drops the least
+   * significant bits, effectively doing an integer division by
+   *`pow(2, shiftIndex)`.
+   *
+   * It is an error if [shiftAmount] is negative.
+   */
+  _BigIntImpl operator >>(int shiftAmount) {
+    if (shiftAmount < 0) {
+      throw new ArgumentError("shift-amount must be positive $shiftAmount");
+    }
+    if (_isZero) return this;
+    final digitShift = shiftAmount ~/ _digitBits;
+    final bitShift = shiftAmount % _digitBits;
+    if (bitShift == 0) {
+      return _drShift(digitShift);
+    }
+    final used = _used;
+    final resultUsed = used - digitShift;
+    if (resultUsed <= 0) {
+      return _isNegative ? _minusOne : zero;
+    }
+    final digits = _digits;
+    final resultDigits = _newDigits(resultUsed);
+    _rsh(digits, used, shiftAmount, resultDigits);
+    final result = new _BigIntImpl._(_isNegative, resultUsed, resultDigits);
+    if (_isNegative) {
+      // Round down if any bit was shifted out.
+      if ((digits[digitShift] & ((1 << bitShift) - 1)) != 0) {
+        return result - one;
+      }
+      for (var i = 0; i < digitShift; i++) {
+        if (digits[i] != 0) {
+          return result - one;
+        }
+      }
+    }
+    return result;
+  }
+
+  /// resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] >> n.
+  /// Returns resultUsed.
+  static int _rShiftDigits(
+      Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
+    final digitShift = n ~/ _digitBits;
+    final bitShift = n % _digitBits;
+    if (bitShift == 0) {
+      return _drShiftDigits(xDigits, xUsed, digitShift, resultDigits);
+    }
+    var resultUsed = xUsed - digitShift;
+    if (resultUsed <= 0) {
+      return 0;
+    }
+    assert(resultDigits.length >= resultUsed + (resultUsed & 1));
+    _rsh(xDigits, xUsed, n, resultDigits);
+    if (resultDigits[resultUsed - 1] == 0) {
+      resultUsed--; // Clamp result.
+    } else if (resultUsed.isOdd) {
+      resultDigits[resultUsed] = 0;
+    }
+    return resultUsed;
+  }
+
+  /// Compares this to [other] taking the absolute value of both operands.
+  ///
+  /// Returns 0 if abs(this) == abs(other); a positive number if
+  /// abs(this) > abs(other); and a negative number if abs(this) < abs(other).
+  int _absCompare(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    return _compareDigits(_digits, _used, other._digits, other._used);
+  }
+
+  /**
+   * Compares this to `other`.
+   *
+   * Returns a negative number if `this` is less than `other`, zero if they are
+   * equal, and a positive number if `this` is greater than `other`.
+   */
+  int compareTo(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (_isNegative == other._isNegative) {
+      var result = _absCompare(other);
+      // Use 0 - result to avoid negative zero in JavaScript.
+      return _isNegative ? 0 - result : result;
+    }
+    return _isNegative ? -1 : 1;
+  }
+
+  /// Compares `digits[0..used-1]` with `otherDigits[0..otherUsed-1]`.
+  ///
+  /// Returns 0 if equal; a positive number if larger;
+  /// and a negative number if smaller.
+  static int _compareDigits(
+      Uint32List digits, int used, Uint32List otherDigits, int otherUsed) {
+    var result = used - otherUsed;
+    if (result == 0) {
+      for (int i = used - 1; i >= 0; i--) {
+        result = digits[i] - otherDigits[i];
+        if (result != 0) return result;
+      }
+    }
+    return result;
+  }
+
+  /// resultDigits[0..used] = digits[0..used-1] + otherDigits[0..otherUsed-1].
+  /// used >= otherUsed > 0.
+  ///
+  /// Note: This function may be intrinsified.
+  @pragma("vm:never-inline")
+  static void _absAdd(Uint32List digits, int used, Uint32List otherDigits,
+      int otherUsed, Uint32List resultDigits) {
+    assert(used >= otherUsed && otherUsed > 0);
+    var carry = 0;
+    for (var i = 0; i < otherUsed; i++) {
+      carry += digits[i] + otherDigits[i];
+      resultDigits[i] = carry & _digitMask;
+      carry >>= _digitBits;
+    }
+    for (var i = otherUsed; i < used; i++) {
+      carry += digits[i];
+      resultDigits[i] = carry & _digitMask;
+      carry >>= _digitBits;
+    }
+    resultDigits[used] = carry;
+  }
+
+  /// resultDigits[0..used-1] = digits[0..used-1] - otherDigits[0..otherUsed-1].
+  /// used >= otherUsed > 0.
+  ///
+  /// Note: This function may be intrinsified.
+  @pragma("vm:never-inline")
+  static void _absSub(Uint32List digits, int used, Uint32List otherDigits,
+      int otherUsed, Uint32List resultDigits) {
+    assert(used >= otherUsed && otherUsed > 0);
+    var carry = 0;
+    for (var i = 0; i < otherUsed; i++) {
+      carry += digits[i] - otherDigits[i];
+      resultDigits[i] = carry & _digitMask;
+      carry >>= _digitBits;
+    }
+    for (var i = otherUsed; i < used; i++) {
+      carry += digits[i];
+      resultDigits[i] = carry & _digitMask;
+      carry >>= _digitBits;
+    }
+  }
+
+  /// Returns `abs(this) + abs(other)` with sign set according to [isNegative].
+  _BigIntImpl _absAddSetSign(_BigIntImpl other, bool isNegative) {
+    var used = _used;
+    var otherUsed = other._used;
+    if (used < otherUsed) {
+      return other._absAddSetSign(this, isNegative);
+    }
+    if (used == 0) {
+      assert(!isNegative);
+      return zero;
+    }
+    if (otherUsed == 0) {
+      return _isNegative == isNegative ? this : -this;
+    }
+    var resultUsed = used + 1;
+    var resultDigits = _newDigits(resultUsed);
+    _absAdd(_digits, used, other._digits, otherUsed, resultDigits);
+    return new _BigIntImpl._(isNegative, resultUsed, resultDigits);
+  }
+
+  /// Returns `abs(this) - abs(other)` with sign set according to [isNegative].
+  ///
+  /// Requirement: `abs(this) >= abs(other)`.
+  _BigIntImpl _absSubSetSign(_BigIntImpl other, bool isNegative) {
+    assert(_absCompare(other) >= 0);
+    var used = _used;
+    if (used == 0) {
+      assert(!isNegative);
+      return zero;
+    }
+    var otherUsed = other._used;
+    if (otherUsed == 0) {
+      return _isNegative == isNegative ? this : -this;
+    }
+    var resultDigits = _newDigits(used);
+    _absSub(_digits, used, other._digits, otherUsed, resultDigits);
+    return new _BigIntImpl._(isNegative, used, resultDigits);
+  }
+
+  /// Returns `abs(this) & abs(other)` with sign set according to [isNegative].
+  _BigIntImpl _absAndSetSign(_BigIntImpl other, bool isNegative) {
+    var resultUsed = _min(_used, other._used);
+    var digits = _digits;
+    var otherDigits = other._digits;
+    var resultDigits = _newDigits(resultUsed);
+    for (var i = 0; i < resultUsed; i++) {
+      resultDigits[i] = digits[i] & otherDigits[i];
+    }
+    return new _BigIntImpl._(isNegative, resultUsed, resultDigits);
+  }
+
+  /// Returns `abs(this) &~ abs(other)` with sign set according to [isNegative].
+  _BigIntImpl _absAndNotSetSign(_BigIntImpl other, bool isNegative) {
+    var resultUsed = _used;
+    var digits = _digits;
+    var otherDigits = other._digits;
+    var resultDigits = _newDigits(resultUsed);
+    var m = _min(resultUsed, other._used);
+    for (var i = 0; i < m; i++) {
+      resultDigits[i] = digits[i] & ~otherDigits[i];
+    }
+    for (var i = m; i < resultUsed; i++) {
+      resultDigits[i] = digits[i];
+    }
+    return new _BigIntImpl._(isNegative, resultUsed, resultDigits);
+  }
+
+  /// Returns `abs(this) | abs(other)` with sign set according to [isNegative].
+  _BigIntImpl _absOrSetSign(_BigIntImpl other, bool isNegative) {
+    var used = _used;
+    var otherUsed = other._used;
+    var resultUsed = _max(used, otherUsed);
+    var digits = _digits;
+    var otherDigits = other._digits;
+    var resultDigits = _newDigits(resultUsed);
+    var l, m;
+    if (used < otherUsed) {
+      l = other;
+      m = used;
+    } else {
+      l = this;
+      m = otherUsed;
+    }
+    for (var i = 0; i < m; i++) {
+      resultDigits[i] = digits[i] | otherDigits[i];
+    }
+    var lDigits = l._digits;
+    for (var i = m; i < resultUsed; i++) {
+      resultDigits[i] = lDigits[i];
+    }
+    return new _BigIntImpl._(isNegative, resultUsed, resultDigits);
+  }
+
+  /// Returns `abs(this) ^ abs(other)` with sign set according to [isNegative].
+  _BigIntImpl _absXorSetSign(_BigIntImpl other, bool isNegative) {
+    var used = _used;
+    var otherUsed = other._used;
+    var resultUsed = _max(used, otherUsed);
+    var digits = _digits;
+    var otherDigits = other._digits;
+    var resultDigits = _newDigits(resultUsed);
+    var l, m;
+    if (used < otherUsed) {
+      l = other;
+      m = used;
+    } else {
+      l = this;
+      m = otherUsed;
+    }
+    for (var i = 0; i < m; i++) {
+      resultDigits[i] = digits[i] ^ otherDigits[i];
+    }
+    var lDigits = l._digits;
+    for (var i = m; i < resultUsed; i++) {
+      resultDigits[i] = lDigits[i];
+    }
+    return new _BigIntImpl._(isNegative, resultUsed, resultDigits);
+  }
+
+  /**
+   * Bit-wise and operator.
+   *
+   * Treating both `this` and [other] as sufficiently large two's component
+   * integers, the result is a number with only the bits set that are set in
+   * both `this` and [other]
+   *
+   * Of both operands are negative, the result is negative, otherwise
+   * the result is non-negative.
+   */
+  _BigIntImpl operator &(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (_isZero || other._isZero) return zero;
+    if (_isNegative == other._isNegative) {
+      if (_isNegative) {
+        // (-this) & (-other) == ~(this-1) & ~(other-1)
+        //                    == ~((this-1) | (other-1))
+        //                    == -(((this-1) | (other-1)) + 1)
+        _BigIntImpl this1 = _absSubSetSign(one, true);
+        _BigIntImpl other1 = other._absSubSetSign(one, true);
+        // Result cannot be zero if this and other are negative.
+        return this1._absOrSetSign(other1, true)._absAddSetSign(one, true);
+      }
+      return _absAndSetSign(other, false);
+    }
+    // _isNegative != other._isNegative
+    var p, n;
+    if (_isNegative) {
+      p = other;
+      n = this;
+    } else {
+      // & is symmetric.
+      p = this;
+      n = other;
+    }
+    // p & (-n) == p & ~(n-1) == p &~ (n-1)
+    var n1 = n._absSubSetSign(one, false);
+    return p._absAndNotSetSign(n1, false);
+  }
+
+  /**
+   * Bit-wise or operator.
+   *
+   * Treating both `this` and [other] as sufficiently large two's component
+   * integers, the result is a number with the bits set that are set in either
+   * of `this` and [other]
+   *
+   * If both operands are non-negative, the result is non-negative,
+   * otherwise the result us negative.
+   */
+  _BigIntImpl operator |(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (_isZero) return other;
+    if (other._isZero) return this;
+    if (_isNegative == other._isNegative) {
+      if (_isNegative) {
+        // (-this) | (-other) == ~(this-1) | ~(other-1)
+        //                    == ~((this-1) & (other-1))
+        //                    == -(((this-1) & (other-1)) + 1)
+        var this1 = _absSubSetSign(one, true);
+        var other1 = other._absSubSetSign(one, true);
+        // Result cannot be zero if this and a are negative.
+        return this1._absAndSetSign(other1, true)._absAddSetSign(one, true);
+      }
+      return _absOrSetSign(other, false);
+    }
+    // _neg != a._neg
+    var p, n;
+    if (_isNegative) {
+      p = other;
+      n = this;
+    } else {
+      // | is symmetric.
+      p = this;
+      n = other;
+    }
+    // p | (-n) == p | ~(n-1) == ~((n-1) &~ p) == -(~((n-1) &~ p) + 1)
+    var n1 = n._absSubSetSign(one, true);
+    // Result cannot be zero if only one of this or a is negative.
+    return n1._absAndNotSetSign(p, true)._absAddSetSign(one, true);
+  }
+
+  /**
+   * Bit-wise exclusive-or operator.
+   *
+   * Treating both `this` and [other] as sufficiently large two's component
+   * integers, the result is a number with the bits set that are set in one,
+   * but not both, of `this` and [other]
+   *
+   * If the operands have the same sign, the result is non-negative,
+   * otherwise the result is negative.
+   */
+  _BigIntImpl operator ^(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (_isZero) return other;
+    if (other._isZero) return this;
+    if (_isNegative == other._isNegative) {
+      if (_isNegative) {
+        // (-this) ^ (-other) == ~(this-1) ^ ~(other-1) == (this-1) ^ (other-1)
+        var this1 = _absSubSetSign(one, true);
+        var other1 = other._absSubSetSign(one, true);
+        return this1._absXorSetSign(other1, false);
+      }
+      return _absXorSetSign(other, false);
+    }
+    // _isNegative != a._isNegative
+    var p, n;
+    if (_isNegative) {
+      p = other;
+      n = this;
+    } else {
+      // ^ is symmetric.
+      p = this;
+      n = other;
+    }
+    // p ^ (-n) == p ^ ~(n-1) == ~(p ^ (n-1)) == -((p ^ (n-1)) + 1)
+    var n1 = n._absSubSetSign(one, true);
+    // Result cannot be zero if only one of this or a is negative.
+    return p._absXorSetSign(n1, true)._absAddSetSign(one, true);
+  }
+
+  /**
+   * The bit-wise negate operator.
+   *
+   * Treating `this` as a sufficiently large two's component integer,
+   * the result is a number with the opposite bits set.
+   *
+   * This maps any integer `x` to `-x - 1`.
+   */
+  _BigIntImpl operator ~() {
+    if (_isZero) return _minusOne;
+    if (_isNegative) {
+      // ~(-this) == ~(~(this-1)) == this-1
+      return _absSubSetSign(one, false);
+    }
+    // ~this == -this-1 == -(this+1)
+    // Result cannot be zero if this is positive.
+    return _absAddSetSign(one, true);
+  }
+
+  /// Addition operator.
+  _BigIntImpl operator +(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (_isZero) return other;
+    if (other._isZero) return this;
+    var isNegative = _isNegative;
+    if (isNegative == other._isNegative) {
+      // this + other == this + other
+      // (-this) + (-other) == -(this + other)
+      return _absAddSetSign(other, isNegative);
+    }
+    // this + (-other) == this - other == -(this - other)
+    // (-this) + other == other - this == -(this - other)
+    if (_absCompare(other) >= 0) {
+      return _absSubSetSign(other, isNegative);
+    }
+    return other._absSubSetSign(this, !isNegative);
+  }
+
+  /// Subtraction operator.
+  _BigIntImpl operator -(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (_isZero) return -other;
+    if (other._isZero) return this;
+    var isNegative = _isNegative;
+    if (isNegative != other._isNegative) {
+      // this - (-other) == this + other
+      // (-this) - other == -(this + other)
+      return _absAddSetSign(other, isNegative);
+    }
+    // this - other == this - a == -(this - other)
+    // (-this) - (-other) == other - this == -(this - other)
+    if (_absCompare(other) >= 0) {
+      return _absSubSetSign(other, isNegative);
+    }
+    return other._absSubSetSign(this, !isNegative);
+  }
+
+  /// Multiplies `xDigits[xIndex]` with `multiplicandDigits` and adds the result
+  /// to `accumulatorDigits`.
+  ///
+  /// The `multiplicandDigits` in the range `i` to `i`+`n`-1 are the
+  /// multiplicand digits.
+  ///
+  /// The `accumulatorDigits` in the range `j` to `j`+`n`-1 are the accumulator
+  /// digits.
+  ///
+  /// Concretely:
+  /// `accumulatorDigits[j..j+n] += xDigits[xIndex] * m_digits[i..i+n-1]`.
+  /// Returns 1.
+  ///
+  /// Note: This function may be intrinsified. Intrinsics on 64-bit platforms
+  /// process digit pairs at even indices and returns 2.
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  @pragma("vm:never-inline")
+  static int _mulAdd(
+      Uint32List xDigits,
+      int xIndex,
+      Uint32List multiplicandDigits,
+      int i,
+      Uint32List accumulatorDigits,
+      int j,
+      int n) {
+    int x = xDigits[xIndex];
+    if (x == 0) {
+      // No-op if x is 0.
+      return 1;
+    }
+    int carry = 0;
+    int xl = x & _halfDigitMask;
+    int xh = x >> _halfDigitBits;
+    while (--n >= 0) {
+      int ml = multiplicandDigits[i] & _halfDigitMask;
+      int mh = multiplicandDigits[i++] >> _halfDigitBits;
+      int ph = xh * ml + mh * xl;
+      int pl = xl * ml +
+          ((ph & _halfDigitMask) << _halfDigitBits) +
+          accumulatorDigits[j] +
+          carry;
+      carry = (pl >> _digitBits) + (ph >> _halfDigitBits) + xh * mh;
+      accumulatorDigits[j++] = pl & _digitMask;
+    }
+    while (carry != 0) {
+      int l = accumulatorDigits[j] + carry;
+      carry = l >> _digitBits;
+      accumulatorDigits[j++] = l & _digitMask;
+    }
+    return 1;
+  }
+
+  /// Multiplies `xDigits[i]` with `xDigits` and adds the result to
+  /// `accumulatorDigits`.
+  ///
+  /// The `xDigits` in the range `i` to `used`-1 are the multiplicand digits.
+  ///
+  /// The `accumulatorDigits` in the range 2*`i` to `i`+`used`-1 are the
+  /// accumulator digits.
+  ///
+  /// Concretely:
+  /// `accumulatorDigits[2*i..i+used-1] += xDigits[i]*xDigits[i] +
+  /// 2*xDigits[i]*xDigits[i+1..used-1]`.
+  /// Returns 1.
+  ///
+  /// Note: This function may be intrinsified. Intrinsics on 64-bit platforms
+  /// process digit pairs at even indices and returns 2.
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  @pragma("vm:never-inline")
+  static int _sqrAdd(
+      Uint32List xDigits, int i, Uint32List acculumatorDigits, int used) {
+    int x = xDigits[i];
+    if (x == 0) return 1;
+    int j = 2 * i;
+    int carry = 0;
+    int xl = x & _halfDigitMask;
+    int xh = x >> _halfDigitBits;
+    int ph = 2 * xh * xl;
+    int pl = xl * xl +
+        ((ph & _halfDigitMask) << _halfDigitBits) +
+        acculumatorDigits[j];
+    carry = (pl >> _digitBits) + (ph >> _halfDigitBits) + xh * xh;
+    acculumatorDigits[j] = pl & _digitMask;
+    x <<= 1;
+    xl = x & _halfDigitMask;
+    xh = x >> _halfDigitBits;
+    int n = used - i - 1;
+    int k = i + 1;
+    j++;
+    while (--n >= 0) {
+      int l = xDigits[k] & _halfDigitMask;
+      int h = xDigits[k++] >> _halfDigitBits;
+      int ph = xh * l + h * xl;
+      int pl = xl * l +
+          ((ph & _halfDigitMask) << _halfDigitBits) +
+          acculumatorDigits[j] +
+          carry;
+      carry = (pl >> _digitBits) + (ph >> _halfDigitBits) + xh * h;
+      acculumatorDigits[j++] = pl & _digitMask;
+    }
+    carry += acculumatorDigits[i + used];
+    if (carry >= _digitBase) {
+      acculumatorDigits[i + used] = carry - _digitBase;
+      acculumatorDigits[i + used + 1] = 1;
+    } else {
+      acculumatorDigits[i + used] = carry;
+    }
+    return 1;
+  }
+
+  /// Multiplication operator.
+  _BigIntImpl operator *(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    var used = _used;
+    var otherUsed = other._used;
+    if (used == 0 || otherUsed == 0) {
+      return zero;
+    }
+    var resultUsed = used + otherUsed;
+    var digits = _digits;
+    var otherDigits = other._digits;
+    var resultDigits = _newDigits(resultUsed);
+    var i = 0;
+    while (i < otherUsed) {
+      i += _mulAdd(otherDigits, i, digits, 0, resultDigits, i, used);
+    }
+    return new _BigIntImpl._(
+        _isNegative != other._isNegative, resultUsed, resultDigits);
+  }
+
+  // resultDigits[0..resultUsed-1] =
+  //     xDigits[0..xUsed-1]*otherDigits[0..otherUsed-1].
+  // Returns resultUsed = xUsed + otherUsed.
+  static int _mulDigits(Uint32List xDigits, int xUsed, Uint32List otherDigits,
+      int otherUsed, Uint32List resultDigits) {
+    var resultUsed = xUsed + otherUsed;
+    var i = resultUsed + (resultUsed & 1);
+    assert(resultDigits.length >= i);
+    while (--i >= 0) {
+      resultDigits[i] = 0;
+    }
+    i = 0;
+    while (i < otherUsed) {
+      i += _mulAdd(otherDigits, i, xDigits, 0, resultDigits, i, xUsed);
+    }
+    return resultUsed;
+  }
+
+  // resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1]^2.
+  // Returns resultUsed = 2*xUsed.
+  static int _sqrDigits(
+      Uint32List xDigits, int xUsed, Uint32List resultDigits) {
+    var resultUsed = 2 * xUsed;
+    assert(resultDigits.length >= resultUsed);
+    // Since resultUsed is even, no need for a leading zero for
+    // 64-bit processing.
+    var i = resultUsed;
+    while (--i >= 0) {
+      resultDigits[i] = 0;
+    }
+    i = 0;
+    while (i < xUsed - 1) {
+      i += _sqrAdd(xDigits, i, resultDigits, xUsed);
+    }
+    // The last step is already done if digit pairs were processed above.
+    if (i < xUsed) {
+      _mulAdd(xDigits, i, xDigits, i, resultDigits, 2 * i, 1);
+    }
+    return resultUsed;
+  }
+
+  // Indices of the arguments of _estimateQuotientDigit.
+  // For 64-bit processing by intrinsics on 64-bit platforms, the top digit pair
+  // of the divisor is provided in the args array, and a 64-bit estimated
+  // quotient is returned. However, on 32-bit platforms, the low 32-bit digit is
+  // ignored and only one 32-bit digit is returned as the estimated quotient.
+  static const int _divisorLowTopDigit = 0; // Low digit of top pair of divisor.
+  static const int _divisorTopDigit = 1; // Top digit of divisor.
+  static const int _quotientDigit = 2; // Estimated quotient.
+  static const int _quotientHighDigit = 3; // High digit of estimated quotient.
+
+  /// Estimate `args[_quotientDigit] = digits[i-1..i] ~/ args[_divisorTopDigit]`
+  /// Returns 1.
+  ///
+  /// Note: This function may be intrinsified. Intrinsics on 64-bit platforms
+  /// process a digit pair (i always odd):
+  /// Estimate `args[_quotientDigit.._quotientHighDigit] = digits[i-3..i] ~/
+  /// args[_divisorLowTopDigit.._divisorTopDigit]`.
+  /// Returns 2.
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  @pragma("vm:never-inline")
+  static int _estimateQuotientDigit(Uint32List args, Uint32List digits, int i) {
+    // Verify that digit pairs are accessible for 64-bit processing.
+    assert(digits.length >= 4);
+    if (digits[i] == args[_divisorTopDigit]) {
+      args[_quotientDigit] = _digitMask;
+    } else {
+      // Chop off one bit, since a Mint cannot hold 2 digits.
+      var quotientDigit =
+          ((digits[i] << (_digitBits - 1)) | (digits[i - 1] >> 1)) ~/
+              (args[_divisorTopDigit] >> 1);
+      if (quotientDigit > _digitMask) {
+        args[_quotientDigit] = _digitMask;
+      } else {
+        args[_quotientDigit] = quotientDigit;
+      }
+    }
+    return 1;
+  }
+
+  /// Returns `trunc(this / other)`, with `other != 0`.
+  _BigIntImpl _div(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    assert(other._used > 0);
+    if (_used < other._used) {
+      return zero;
+    }
+    _divRem(other);
+    // Return quotient, i.e.
+    // _lastQuoRem_digits[_lastRem_used.._lastQuoRem_used-1] with proper sign.
+    var lastQuo_used = _lastQuoRemUsed - _lastRemUsed;
+    var quo_digits = _cloneDigits(
+        _lastQuoRemDigits, _lastRemUsed, _lastQuoRemUsed, lastQuo_used);
+    var quo = new _BigIntImpl._(false, lastQuo_used, quo_digits);
+    if ((_isNegative != other._isNegative) && (quo._used > 0)) {
+      quo = -quo;
+    }
+    return quo;
+  }
+
+  /// Returns `this - other * trunc(this / other)`, with `other != 0`.
+  _BigIntImpl _rem(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    assert(other._used > 0);
+    if (_used < other._used) {
+      return this;
+    }
+    _divRem(other);
+    // Return remainder, i.e.
+    // denormalized _lastQuoRem_digits[0.._lastRem_used-1] with proper sign.
+    var remDigits =
+        _cloneDigits(_lastQuoRemDigits, 0, _lastRemUsed, _lastRemUsed);
+    var rem = new _BigIntImpl._(false, _lastRemUsed, remDigits);
+    if (_lastRem_nsh > 0) {
+      rem = rem >> _lastRem_nsh; // Denormalize remainder.
+    }
+    if (_isNegative && (rem._used > 0)) {
+      rem = -rem;
+    }
+    return rem;
+  }
+
+  /// Computes this ~/ other and this.remainder(other).
+  ///
+  /// Stores the result in [_lastQuoRemDigits], [_lastQuoRemUsed] and
+  /// [_lastRemUsed]. The [_lastQuoRemDigits] contains the digits of *both*, the
+  /// quotient and the remainder.
+  ///
+  /// Caches the input to avoid doing the work again when users write
+  /// `a ~/ b` followed by a `a % b`.
+  void _divRem(_BigIntImpl other) {
+    // Check if result is already cached.
+    if ((this._used == _lastDividendUsed) &&
+        (other._used == _lastDivisorUsed) &&
+        identical(this._digits, _lastDividendDigits) &&
+        identical(other._digits, _lastDivisorDigits)) {
+      return;
+    }
+    assert(_used >= other._used);
+
+    var nsh = _digitBits - other._digits[other._used - 1].bitLength;
+    // For 64-bit processing, make sure other has an even number of digits.
+    if (other._used.isOdd) {
+      nsh += _digitBits;
+    }
+    // Concatenated positive quotient and normalized positive remainder.
+    // The resultDigits can have at most one more digit than the dividend.
+    Uint32List resultDigits;
+    int resultUsed;
+    // Normalized positive divisor (referred to as 'y').
+    // The normalized divisor has the most-significant bit of its most
+    // significant digit set.
+    // This makes estimating the quotient easier.
+    Uint32List yDigits;
+    int yUsed;
+    if (nsh > 0) {
+      // Extra digits for normalization, also used for possible _mulAdd carry.
+      var numExtraDigits = (nsh + _digitBits - 1) ~/ _digitBits + 1;
+      yDigits = _newDigits(other._used + numExtraDigits);
+      yUsed = _lShiftDigits(other._digits, other._used, nsh, yDigits);
+      resultDigits = _newDigits(_used + numExtraDigits);
+      resultUsed = _lShiftDigits(_digits, _used, nsh, resultDigits);
+    } else {
+      yDigits = other._digits;
+      yUsed = other._used;
+      // Extra digit to hold possible _mulAdd carry.
+      resultDigits = _cloneDigits(_digits, 0, _used, _used + 1);
+      resultUsed = _used;
+    }
+    Uint32List args = _newDigits(4);
+    args[_divisorLowTopDigit] = yDigits[yUsed - 2];
+    args[_divisorTopDigit] = yDigits[yUsed - 1];
+    // For 64-bit processing, make sure yUsed, i, and j are even.
+    assert(yUsed.isEven);
+    var i = resultUsed + (resultUsed & 1);
+    var j = i - yUsed;
+    // tmpDigits is a temporary array of i (even resultUsed) digits.
+    var tmpDigits = _newDigits(i);
+    var tmpUsed = _dlShiftDigits(yDigits, yUsed, j, tmpDigits);
+    // Explicit first division step in case normalized dividend is larger or
+    // equal to shifted normalized divisor.
+    if (_compareDigits(resultDigits, resultUsed, tmpDigits, tmpUsed) >= 0) {
+      assert(i == resultUsed);
+      resultDigits[resultUsed++] = 1; // Quotient = 1.
+      // Subtract divisor from remainder.
+      _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+    } else {
+      // Account for possible carry in _mulAdd step.
+      resultDigits[resultUsed++] = 0;
+    }
+    if (resultUsed.isOdd) {
+      resultDigits[resultUsed] = 0; // Leading zero for 64-bit processing.
+    }
+    // Negate y so we can later use _mulAdd instead of non-existent _mulSub.
+    var nyDigits = _newDigits(yUsed + 2);
+    nyDigits[yUsed] = 1;
+    _absSub(nyDigits, yUsed + 1, yDigits, yUsed, nyDigits);
+    // nyDigits is read-only and has yUsed digits (possibly including several
+    // leading zeros) plus a leading zero for 64-bit processing.
+    // resultDigits is modified during iteration.
+    // resultDigits[0..yUsed-1] is the current remainder.
+    // resultDigits[yUsed..resultUsed-1] is the current quotient.
+    --i;
+    while (j > 0) {
+      var d0 = _estimateQuotientDigit(args, resultDigits, i);
+      j -= d0;
+      var d1 =
+          _mulAdd(args, _quotientDigit, nyDigits, 0, resultDigits, j, yUsed);
+      // _estimateQuotientDigit and _mulAdd must agree on the number of digits
+      // to process.
+      assert(d0 == d1);
+      if (d0 == 1) {
+        if (resultDigits[i] < args[_quotientDigit]) {
+          // Reusing the already existing tmpDigits array.
+          var tmpUsed = _dlShiftDigits(nyDigits, yUsed, j, tmpDigits);
+          _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+          while (resultDigits[i] < --args[_quotientDigit]) {
+            _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+          }
+        }
+      } else {
+        assert(d0 == 2);
+        assert(resultDigits[i] <= args[_quotientHighDigit]);
+        if (resultDigits[i] < args[_quotientHighDigit] ||
+            resultDigits[i - 1] < args[_quotientDigit]) {
+          // Reusing the already existing tmpDigits array.
+          var tmpUsed = _dlShiftDigits(nyDigits, yUsed, j, tmpDigits);
+          _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+          if (args[_quotientDigit] == 0) {
+            --args[_quotientHighDigit];
+          }
+          --args[_quotientDigit];
+          assert(resultDigits[i] <= args[_quotientHighDigit]);
+          while (resultDigits[i] < args[_quotientHighDigit] ||
+              resultDigits[i - 1] < args[_quotientDigit]) {
+            _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+            if (args[_quotientDigit] == 0) {
+              --args[_quotientHighDigit];
+            }
+            --args[_quotientDigit];
+            assert(resultDigits[i] <= args[_quotientHighDigit]);
+          }
+        }
+      }
+      i -= d0;
+    }
+    // Cache result.
+    _lastDividendDigits = _digits;
+    _lastDividendUsed = _used;
+    _lastDivisorDigits = other._digits;
+    _lastDivisorUsed = other._used;
+    _lastQuoRemDigits = resultDigits;
+    _lastQuoRemUsed = resultUsed;
+    _lastRemUsed = yUsed;
+    _lastRem_nsh = nsh;
+  }
+
+  // Customized version of _rem() minimizing allocations for use in reduction.
+  // Input:
+  //   xDigits[0..xUsed-1]: positive dividend.
+  //   yDigits[0..yUsed-1]: normalized positive divisor.
+  //   nyDigits[0..yUsed-1]: negated yDigits.
+  //   nsh: normalization shift amount.
+  //   args: top y digit(s) and place holder for estimated quotient digit(s).
+  //   tmpDigits: temp array of 2*yUsed digits.
+  //   resultDigits: result digits array large enough to temporarily hold
+  //                 concatenated quotient and normalized remainder.
+  // Output:
+  //   resultDigits[0..resultUsed-1]: positive remainder.
+  // Returns resultUsed.
+  static int _remDigits(
+      Uint32List xDigits,
+      int xUsed,
+      Uint32List yDigits,
+      int yUsed,
+      Uint32List nyDigits,
+      int nsh,
+      Uint32List args,
+      Uint32List tmpDigits,
+      Uint32List resultDigits) {
+    // Initialize resultDigits to normalized positive dividend.
+    var resultUsed = _lShiftDigits(xDigits, xUsed, nsh, resultDigits);
+    // For 64-bit processing, make sure yUsed, i, and j are even.
+    assert(yUsed.isEven);
+    var i = resultUsed + (resultUsed & 1);
+    var j = i - yUsed;
+    var tmpUsed = _dlShiftDigits(yDigits, yUsed, j, tmpDigits);
+    // Explicit first division step in case normalized dividend is larger or
+    // equal to shifted normalized divisor.
+    if (_compareDigits(resultDigits, resultUsed, tmpDigits, tmpUsed) >= 0) {
+      assert(i == resultUsed);
+      resultDigits[resultUsed++] = 1; // Quotient = 1.
+      // Subtract divisor from remainder.
+      _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+    } else {
+      // Account for possible carry in _mulAdd step.
+      resultDigits[resultUsed++] = 0;
+    }
+    if (resultUsed.isOdd) {
+      resultDigits[resultUsed] = 0; // Leading zero for 64-bit processing.
+    }
+    // Negated yDigits passed in nyDigits allow the use of _mulAdd instead of
+    // unimplemented _mulSub.
+    // nyDigits is read-only and has yUsed digits (possibly including several
+    // leading zeros) plus a leading zero for 64-bit processing.
+    // resultDigits is modified during iteration.
+    // resultDigits[0..yUsed-1] is the current remainder.
+    // resultDigits[yUsed..resultUsed-1] is the current quotient.
+    --i;
+    while (j > 0) {
+      var d0 = _estimateQuotientDigit(args, resultDigits, i);
+      j -= d0;
+      var d1 =
+          _mulAdd(args, _quotientDigit, nyDigits, 0, resultDigits, j, yUsed);
+      // _estimateQuotientDigit and _mulAdd must agree on the number of digits
+      // to process.
+      assert(d0 == d1);
+      if (d0 == 1) {
+        if (resultDigits[i] < args[_quotientDigit]) {
+          var tmpUsed = _dlShiftDigits(nyDigits, yUsed, j, tmpDigits);
+          _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+          while (resultDigits[i] < --args[_quotientDigit]) {
+            _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+          }
+        }
+      } else {
+        assert(d0 == 2);
+        assert(resultDigits[i] <= args[_quotientHighDigit]);
+        if ((resultDigits[i] < args[_quotientHighDigit]) ||
+            (resultDigits[i - 1] < args[_quotientDigit])) {
+          var tmpUsed = _dlShiftDigits(nyDigits, yUsed, j, tmpDigits);
+          _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+          if (args[_quotientDigit] == 0) {
+            --args[_quotientHighDigit];
+          }
+          --args[_quotientDigit];
+          assert(resultDigits[i] <= args[_quotientHighDigit]);
+          while ((resultDigits[i] < args[_quotientHighDigit]) ||
+              (resultDigits[i - 1] < args[_quotientDigit])) {
+            _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+            if (args[_quotientDigit] == 0) {
+              --args[_quotientHighDigit];
+            }
+            --args[_quotientDigit];
+            assert(resultDigits[i] <= args[_quotientHighDigit]);
+          }
+        }
+      }
+      i -= d0;
+    }
+    // Return remainder, i.e. denormalized resultDigits[0..yUsed-1].
+    resultUsed = yUsed;
+    if (nsh > 0) {
+      // Denormalize remainder.
+      resultUsed = _rShiftDigits(resultDigits, resultUsed, nsh, resultDigits);
+    }
+    return resultUsed;
+  }
+
+  int get hashCode {
+    // This is the [Jenkins hash function][1] but using masking to keep
+    // values in SMI range.
+    //
+    // [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function
+
+    int combine(int hash, int value) {
+      hash = 0x1fffffff & (hash + value);
+      hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
+      return hash ^ (hash >> 6);
+    }
+
+    int finish(int hash) {
+      hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
+      hash = hash ^ (hash >> 11);
+      return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
+    }
+
+    if (_isZero) return 6707; // Just a random number.
+    var hash = _isNegative ? 83585 : 429689; // Also random.
+    for (int i = 0; i < _used; i++) {
+      hash = combine(hash, _digits[i]);
+    }
+    return finish(hash);
+  }
+
+  /**
+   * Test whether this value is numerically equal to `other`.
+   *
+   * If [other] is a [_BigIntImpl] returns whether the two operands have the
+   * same value.
+   *
+   * Returns false if `other` is not a [_BigIntImpl].
+   */
+  bool operator ==(Object other) =>
+      other is _BigIntImpl && compareTo(other) == 0;
+
+  /**
+   * Returns the minimum number of bits required to store this big integer.
+   *
+   * The number of bits excludes the sign bit, which gives the natural length
+   * for non-negative (unsigned) values.  Negative values are complemented to
+   * return the bit position of the first bit that differs from the sign bit.
+   *
+   * To find the number of bits needed to store the value as a signed value,
+   * add one, i.e. use `x.bitLength + 1`.
+   *
+   * ```
+   * x.bitLength == (-x-1).bitLength
+   *
+   * new BigInt.from(3).bitLength == 2;   // 00000011
+   * new BigInt.from(2).bitLength == 2;   // 00000010
+   * new BigInt.from(1).bitLength == 1;   // 00000001
+   * new BigInt.from(0).bitLength == 0;   // 00000000
+   * new BigInt.from(-1).bitLength == 0;  // 11111111
+   * new BigInt.from(-2).bitLength == 1;  // 11111110
+   * new BigInt.from(-3).bitLength == 2;  // 11111101
+   * new BigInt.from(-4).bitLength == 2;  // 11111100
+   * ```
+   */
+  int get bitLength {
+    if (_used == 0) return 0;
+    if (_isNegative) return (~this).bitLength;
+    return _digitBits * (_used - 1) + _digits[_used - 1].bitLength;
+  }
+
+  /**
+   * Truncating division operator.
+   *
+   * Performs a truncating integer division, where the remainder is discarded.
+   *
+   * The remainder can be computed using the [remainder] method.
+   *
+   * Examples:
+   * ```
+   * var seven = new BigInt.from(7);
+   * var three = new BigInt.from(3);
+   * seven ~/ three;    // => 2
+   * (-seven) ~/ three; // => -2
+   * seven ~/ -three;   // => -2
+   * seven.remainder(three);    // => 1
+   * (-seven).remainder(three); // => -1
+   * seven.remainder(-three);   // => 1
+   * ```
+   */
+  _BigIntImpl operator ~/(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (other._used == 0) {
+      throw const IntegerDivisionByZeroException();
+    }
+    return _div(other);
+  }
+
+  /**
+   * Returns the remainder of the truncating division of `this` by [other].
+   *
+   * The result `r` of this operation satisfies:
+   * `this == (this ~/ other) * other + r`.
+   * As a consequence the remainder `r` has the same sign as the divider `this`.
+   */
+  _BigIntImpl remainder(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (other._used == 0) {
+      throw const IntegerDivisionByZeroException();
+    }
+    return _rem(other);
+  }
+
+  /// Division operator.
+  double operator /(BigInt other) => this.toDouble() / other.toDouble();
+
+  /** Relational less than operator. */
+  bool operator <(BigInt other) => compareTo(other) < 0;
+
+  /** Relational less than or equal operator. */
+  bool operator <=(BigInt other) => compareTo(other) <= 0;
+
+  /** Relational greater than operator. */
+  bool operator >(BigInt other) => compareTo(other) > 0;
+
+  /** Relational greater than or equal operator. */
+  bool operator >=(BigInt other) => compareTo(other) >= 0;
+
+  /**
+   * Euclidean modulo operator.
+   *
+   * Returns the remainder of the Euclidean division. The Euclidean division of
+   * two integers `a` and `b` yields two integers `q` and `r` such that
+   * `a == b * q + r` and `0 <= r < b.abs()`.
+   *
+   * The sign of the returned value `r` is always positive.
+   *
+   * See [remainder] for the remainder of the truncating division.
+   */
+  _BigIntImpl operator %(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (other._used == 0) {
+      throw const IntegerDivisionByZeroException();
+    }
+    var result = _rem(other);
+    if (result._isNegative) {
+      if (other._isNegative) {
+        result = result - other;
+      } else {
+        result = result + other;
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Returns the sign of this big integer.
+   *
+   * Returns 0 for zero, -1 for values less than zero and
+   * +1 for values greater than zero.
+   */
+  int get sign {
+    if (_used == 0) return 0;
+    return _isNegative ? -1 : 1;
+  }
+
+  /// Whether this big integer is even.
+  bool get isEven => _used == 0 || (_digits[0] & 1) == 0;
+
+  /// Whether this big integer is odd.
+  bool get isOdd => !isEven;
+
+  /// Whether this number is negative.
+  bool get isNegative => _isNegative;
+
+  _BigIntImpl pow(int exponent) {
+    if (exponent < 0) {
+      throw new ArgumentError("Exponent must not be negative: $exponent");
+    }
+    if (exponent == 0) return one;
+
+    // Exponentiation by squaring.
+    var result = one;
+    var base = this;
+    while (exponent != 0) {
+      if ((exponent & 1) == 1) {
+        result *= base;
+      }
+      exponent >>= 1;
+      // Skip unnecessary operation.
+      if (exponent != 0) {
+        base *= base;
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Returns this integer to the power of [exponent] modulo [modulus].
+   *
+   * The [exponent] must be non-negative and [modulus] must be
+   * positive.
+   */
+  _BigIntImpl modPow(BigInt bigExponent, BigInt bigModulus) {
+    _BigIntImpl exponent = bigExponent;
+    _BigIntImpl modulus = bigModulus;
+    if (exponent._isNegative) {
+      throw new ArgumentError("exponent must be positive: $exponent");
+    }
+    if (modulus <= zero) {
+      throw new ArgumentError("modulus must be strictly positive: $modulus");
+    }
+    if (exponent._isZero) return one;
+
+    final exponentBitlen = exponent.bitLength;
+    if (exponentBitlen <= 0) return one;
+    final bool cannotUseMontgomery = modulus.isEven || abs() >= modulus;
+    if (cannotUseMontgomery || exponentBitlen < 64) {
+      _BigIntReduction z = (cannotUseMontgomery || exponentBitlen < 8)
+          ? new _BigIntClassicReduction(modulus)
+          : new _BigIntMontgomeryReduction(modulus);
+      var resultDigits = _newDigits(2 * z._normModulusUsed + 2);
+      var result2Digits = _newDigits(2 * z._normModulusUsed + 2);
+      var gDigits = _newDigits(z._normModulusUsed);
+      var gUsed = z._convert(this, gDigits);
+      // Initialize result with g.
+      // Copy leading zero if any.
+      for (int j = gUsed + (gUsed & 1) - 1; j >= 0; j--) {
+        resultDigits[j] = gDigits[j];
+      }
+      var resultUsed = gUsed;
+      var result2Used;
+      for (int i = exponentBitlen - 2; i >= 0; i--) {
+        result2Used = z._sqr(resultDigits, resultUsed, result2Digits);
+        if (exponent._digits[i ~/ _digitBits] & (1 << (i % _digitBits)) != 0) {
+          resultUsed =
+              z._mul(result2Digits, result2Used, gDigits, gUsed, resultDigits);
+        } else {
+          // Swap result and result2.
+          var tmpDigits = resultDigits;
+          var tmpUsed = resultUsed;
+          resultDigits = result2Digits;
+          resultUsed = result2Used;
+          result2Digits = tmpDigits;
+          result2Used = tmpUsed;
+        }
+      }
+      return z._revert(resultDigits, resultUsed);
+    }
+    var k;
+    if (exponentBitlen < 18)
+      k = 1;
+    else if (exponentBitlen < 48)
+      k = 3;
+    else if (exponentBitlen < 144)
+      k = 4;
+    else if (exponentBitlen < 768)
+      k = 5;
+    else
+      k = 6;
+    _BigIntReduction z = new _BigIntMontgomeryReduction(modulus);
+    var n = 3;
+    final k1 = k - 1;
+    final km = (1 << k) - 1;
+    List gDigits = new List(km + 1);
+    List gUsed = new List(km + 1);
+    gDigits[1] = _newDigits(z._normModulusUsed);
+    gUsed[1] = z._convert(this, gDigits[1]);
+    if (k > 1) {
+      var g2Digits = _newDigits(2 * z._normModulusUsed + 2);
+      var g2Used = z._sqr(gDigits[1], gUsed[1], g2Digits);
+      while (n <= km) {
+        gDigits[n] = _newDigits(2 * z._normModulusUsed + 2);
+        gUsed[n] =
+            z._mul(g2Digits, g2Used, gDigits[n - 2], gUsed[n - 2], gDigits[n]);
+        n += 2;
+      }
+    }
+    var w;
+    var isOne = true;
+    var resultDigits = one._digits;
+    var resultUsed = one._used;
+    var result2Digits = _newDigits(2 * z._normModulusUsed + 2);
+    var result2Used;
+    var exponentDigits = exponent._digits;
+    var j = exponent._used - 1;
+    var i = exponentDigits[j].bitLength - 1;
+    while (j >= 0) {
+      if (i >= k1) {
+        w = (exponentDigits[j] >> (i - k1)) & km;
+      } else {
+        w = (exponentDigits[j] & ((1 << (i + 1)) - 1)) << (k1 - i);
+        if (j > 0) {
+          w |= exponentDigits[j - 1] >> (_digitBits + i - k1);
+        }
+      }
+      n = k;
+      while ((w & 1) == 0) {
+        w >>= 1;
+        --n;
+      }
+      if ((i -= n) < 0) {
+        i += _digitBits;
+        --j;
+      }
+      if (isOne) {
+        // r == 1, don't bother squaring or multiplying it.
+        resultDigits = _newDigits(2 * z._normModulusUsed + 2);
+        resultUsed = gUsed[w];
+        var gwDigits = gDigits[w];
+        var ri = resultUsed + (resultUsed & 1); // Copy leading zero if any.
+        while (--ri >= 0) {
+          resultDigits[ri] = gwDigits[ri];
+        }
+        isOne = false;
+      } else {
+        while (n > 1) {
+          result2Used = z._sqr(resultDigits, resultUsed, result2Digits);
+          resultUsed = z._sqr(result2Digits, result2Used, resultDigits);
+          n -= 2;
+        }
+        if (n > 0) {
+          result2Used = z._sqr(resultDigits, resultUsed, result2Digits);
+        } else {
+          var swapDigits = resultDigits;
+          var swapUsed = resultUsed;
+          resultDigits = result2Digits;
+          resultUsed = result2Used;
+          result2Digits = swapDigits;
+          result2Used = swapUsed;
+        }
+        resultUsed = z._mul(
+            result2Digits, result2Used, gDigits[w], gUsed[w], resultDigits);
+      }
+      while (j >= 0 && (exponentDigits[j] & (1 << i)) == 0) {
+        result2Used = z._sqr(resultDigits, resultUsed, result2Digits);
+        var swapDigits = resultDigits;
+        var swapUsed = resultUsed;
+        resultDigits = result2Digits;
+        resultUsed = result2Used;
+        result2Digits = swapDigits;
+        result2Used = swapUsed;
+        if (--i < 0) {
+          i = _digitBits - 1;
+          --j;
+        }
+      }
+    }
+    assert(!isOne);
+    return z._revert(resultDigits, resultUsed);
+  }
+
+  // If inv is false, returns gcd(x, y).
+  // If inv is true and gcd(x, y) = 1, returns d, so that c*x + d*y = 1.
+  // If inv is true and gcd(x, y) != 1, throws Exception("Not coprime").
+  static _BigIntImpl _binaryGcd(_BigIntImpl x, _BigIntImpl y, bool inv) {
+    var xDigits = x._digits;
+    var yDigits = y._digits;
+    var xUsed = x._used;
+    var yUsed = y._used;
+    var maxUsed = _max(xUsed, yUsed);
+    final maxLen = maxUsed + (maxUsed & 1);
+    xDigits = _cloneDigits(xDigits, 0, xUsed, maxLen);
+    yDigits = _cloneDigits(yDigits, 0, yUsed, maxLen);
+    int shiftAmount = 0;
+    if (inv) {
+      if ((yUsed == 1) && (yDigits[0] == 1)) return one;
+      if ((yUsed == 0) || (yDigits[0].isEven && xDigits[0].isEven)) {
+        throw new Exception("Not coprime");
+      }
+    } else {
+      if (x._isZero) {
+        throw new ArgumentError.value(0, "this", "must not be zero");
+      }
+      if (y._isZero) {
+        throw new ArgumentError.value(0, "other", "must not be zero");
+      }
+      if (((xUsed == 1) && (xDigits[0] == 1)) ||
+          ((yUsed == 1) && (yDigits[0] == 1))) return one;
+      while (((xDigits[0] & 1) == 0) && ((yDigits[0] & 1) == 0)) {
+        _rsh(xDigits, xUsed, 1, xDigits);
+        _rsh(yDigits, yUsed, 1, yDigits);
+        shiftAmount++;
+      }
+      if (shiftAmount >= _digitBits) {
+        var digitShiftAmount = shiftAmount ~/ _digitBits;
+        xUsed -= digitShiftAmount;
+        yUsed -= digitShiftAmount;
+        maxUsed -= digitShiftAmount;
+      }
+      if ((yDigits[0] & 1) == 1) {
+        // Swap x and y.
+        var tmpDigits = xDigits;
+        var tmpUsed = xUsed;
+        xDigits = yDigits;
+        xUsed = yUsed;
+        yDigits = tmpDigits;
+        yUsed = tmpUsed;
+      }
+    }
+    var uDigits = _cloneDigits(xDigits, 0, xUsed, maxLen);
+    var vDigits = _cloneDigits(yDigits, 0, yUsed, maxLen + 2); // +2 for lsh.
+    final bool ac = (xDigits[0] & 1) == 0;
+
+    // Variables a, b, c, and d require one more digit.
+    final abcdUsed = maxUsed + 1;
+    final abcdLen = abcdUsed + (abcdUsed & 1) + 2; // +2 to satisfy _absAdd.
+    var aDigits, bDigits, cDigits, dDigits;
+    bool aIsNegative, bIsNegative, cIsNegative, dIsNegative;
+    if (ac) {
+      aDigits = _newDigits(abcdLen);
+      aIsNegative = false;
+      aDigits[0] = 1;
+      cDigits = _newDigits(abcdLen);
+      cIsNegative = false;
+    }
+    bDigits = _newDigits(abcdLen);
+    bIsNegative = false;
+    dDigits = _newDigits(abcdLen);
+    dIsNegative = false;
+    dDigits[0] = 1;
+
+    while (true) {
+      while ((uDigits[0] & 1) == 0) {
+        _rsh(uDigits, maxUsed, 1, uDigits);
+        if (ac) {
+          if (((aDigits[0] & 1) == 1) || ((bDigits[0] & 1) == 1)) {
+            // a += y
+            if (aIsNegative) {
+              if ((aDigits[maxUsed] != 0) ||
+                  (_compareDigits(aDigits, maxUsed, yDigits, maxUsed)) > 0) {
+                _absSub(aDigits, abcdUsed, yDigits, maxUsed, aDigits);
+              } else {
+                _absSub(yDigits, maxUsed, aDigits, maxUsed, aDigits);
+                aIsNegative = false;
+              }
+            } else {
+              _absAdd(aDigits, abcdUsed, yDigits, maxUsed, aDigits);
+            }
+            // b -= x
+            if (bIsNegative) {
+              _absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
+            } else if ((bDigits[maxUsed] != 0) ||
+                (_compareDigits(bDigits, maxUsed, xDigits, maxUsed) > 0)) {
+              _absSub(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
+            } else {
+              _absSub(xDigits, maxUsed, bDigits, maxUsed, bDigits);
+              bIsNegative = true;
+            }
+          }
+          _rsh(aDigits, abcdUsed, 1, aDigits);
+        } else if ((bDigits[0] & 1) == 1) {
+          // b -= x
+          if (bIsNegative) {
+            _absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
+          } else if ((bDigits[maxUsed] != 0) ||
+              (_compareDigits(bDigits, maxUsed, xDigits, maxUsed) > 0)) {
+            _absSub(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
+          } else {
+            _absSub(xDigits, maxUsed, bDigits, maxUsed, bDigits);
+            bIsNegative = true;
+          }
+        }
+        _rsh(bDigits, abcdUsed, 1, bDigits);
+      }
+      while ((vDigits[0] & 1) == 0) {
+        _rsh(vDigits, maxUsed, 1, vDigits);
+        if (ac) {
+          if (((cDigits[0] & 1) == 1) || ((dDigits[0] & 1) == 1)) {
+            // c += y
+            if (cIsNegative) {
+              if ((cDigits[maxUsed] != 0) ||
+                  (_compareDigits(cDigits, maxUsed, yDigits, maxUsed) > 0)) {
+                _absSub(cDigits, abcdUsed, yDigits, maxUsed, cDigits);
+              } else {
+                _absSub(yDigits, maxUsed, cDigits, maxUsed, cDigits);
+                cIsNegative = false;
+              }
+            } else {
+              _absAdd(cDigits, abcdUsed, yDigits, maxUsed, cDigits);
+            }
+            // d -= x
+            if (dIsNegative) {
+              _absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
+            } else if ((dDigits[maxUsed] != 0) ||
+                (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+              _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
+            } else {
+              _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
+              dIsNegative = true;
+            }
+          }
+          _rsh(cDigits, abcdUsed, 1, cDigits);
+        } else if ((dDigits[0] & 1) == 1) {
+          // d -= x
+          if (dIsNegative) {
+            _absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
+          } else if ((dDigits[maxUsed] != 0) ||
+              (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+            _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
+          } else {
+            _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
+            dIsNegative = true;
+          }
+        }
+        _rsh(dDigits, abcdUsed, 1, dDigits);
+      }
+      if (_compareDigits(uDigits, maxUsed, vDigits, maxUsed) >= 0) {
+        // u -= v
+        _absSub(uDigits, maxUsed, vDigits, maxUsed, uDigits);
+        if (ac) {
+          // a -= c
+          if (aIsNegative == cIsNegative) {
+            var a_cmp_c = _compareDigits(aDigits, abcdUsed, cDigits, abcdUsed);
+            if (a_cmp_c > 0) {
+              _absSub(aDigits, abcdUsed, cDigits, abcdUsed, aDigits);
+            } else {
+              _absSub(cDigits, abcdUsed, aDigits, abcdUsed, aDigits);
+              aIsNegative = !aIsNegative && (a_cmp_c != 0);
+            }
+          } else {
+            _absAdd(aDigits, abcdUsed, cDigits, abcdUsed, aDigits);
+          }
+        }
+        // b -= d
+        if (bIsNegative == dIsNegative) {
+          var b_cmp_d = _compareDigits(bDigits, abcdUsed, dDigits, abcdUsed);
+          if (b_cmp_d > 0) {
+            _absSub(bDigits, abcdUsed, dDigits, abcdUsed, bDigits);
+          } else {
+            _absSub(dDigits, abcdUsed, bDigits, abcdUsed, bDigits);
+            bIsNegative = !bIsNegative && (b_cmp_d != 0);
+          }
+        } else {
+          _absAdd(bDigits, abcdUsed, dDigits, abcdUsed, bDigits);
+        }
+      } else {
+        // v -= u
+        _absSub(vDigits, maxUsed, uDigits, maxUsed, vDigits);
+        if (ac) {
+          // c -= a
+          if (cIsNegative == aIsNegative) {
+            var c_cmp_a = _compareDigits(cDigits, abcdUsed, aDigits, abcdUsed);
+            if (c_cmp_a > 0) {
+              _absSub(cDigits, abcdUsed, aDigits, abcdUsed, cDigits);
+            } else {
+              _absSub(aDigits, abcdUsed, cDigits, abcdUsed, cDigits);
+              cIsNegative = !cIsNegative && (c_cmp_a != 0);
+            }
+          } else {
+            _absAdd(cDigits, abcdUsed, aDigits, abcdUsed, cDigits);
+          }
+        }
+        // d -= b
+        if (dIsNegative == bIsNegative) {
+          var d_cmp_b = _compareDigits(dDigits, abcdUsed, bDigits, abcdUsed);
+          if (d_cmp_b > 0) {
+            _absSub(dDigits, abcdUsed, bDigits, abcdUsed, dDigits);
+          } else {
+            _absSub(bDigits, abcdUsed, dDigits, abcdUsed, dDigits);
+            dIsNegative = !dIsNegative && (d_cmp_b != 0);
+          }
+        } else {
+          _absAdd(dDigits, abcdUsed, bDigits, abcdUsed, dDigits);
+        }
+      }
+      // Exit loop if u == 0.
+      var i = maxUsed;
+      while ((i > 0) && (uDigits[i - 1] == 0)) --i;
+      if (i == 0) break;
+    }
+    if (!inv) {
+      if (shiftAmount > 0) {
+        maxUsed = _lShiftDigits(vDigits, maxUsed, shiftAmount, vDigits);
+      }
+      return new _BigIntImpl._(false, maxUsed, vDigits);
+    }
+    // No inverse if v != 1.
+    var i = maxUsed - 1;
+    while ((i > 0) && (vDigits[i] == 0)) --i;
+    if ((i != 0) || (vDigits[0] != 1)) {
+      throw new Exception("Not coprime");
+    }
+
+    if (dIsNegative) {
+      while ((dDigits[maxUsed] != 0) ||
+          (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+        // d += x, d still negative
+        _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
+      }
+      // d += x
+      _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
+      dIsNegative = false;
+    } else {
+      while ((dDigits[maxUsed] != 0) ||
+          (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) >= 0)) {
+        // d -= x
+        _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
+      }
+    }
+    return new _BigIntImpl._(false, maxUsed, dDigits);
+  }
+
+  /**
+   * Returns the modular multiplicative inverse of this big integer
+   * modulo [modulus].
+   *
+   * The [modulus] must be positive.
+   *
+   * It is an error if no modular inverse exists.
+   */
+  // Returns 1/this % modulus, with modulus > 0.
+  _BigIntImpl modInverse(BigInt bigInt) {
+    _BigIntImpl modulus = bigInt;
+    if (modulus <= zero) {
+      throw new ArgumentError("Modulus must be strictly positive: $modulus");
+    }
+    if (modulus == one) return zero;
+    var tmp = this;
+    if (tmp._isNegative || (tmp._absCompare(modulus) >= 0)) {
+      tmp %= modulus;
+    }
+    return _binaryGcd(modulus, tmp, true);
+  }
+
+  /**
+   * Returns the greatest common divisor of this big integer and [other].
+   *
+   * If either number is non-zero, the result is the numerically greatest
+   * integer dividing both `this` and `other`.
+   *
+   * The greatest common divisor is independent of the order,
+   * so `x.gcd(y)` is  always the same as `y.gcd(x)`.
+   *
+   * For any integer `x`, `x.gcd(x)` is `x.abs()`.
+   *
+   * If both `this` and `other` is zero, the result is also zero.
+   */
+  _BigIntImpl gcd(BigInt bigInt) {
+    _BigIntImpl other = bigInt;
+    if (_isZero) return other.abs();
+    if (other._isZero) return this.abs();
+    return _binaryGcd(this, other, false);
+  }
+
+  /**
+   * Returns the least significant [width] bits of this big integer as a
+   * non-negative number (i.e. unsigned representation).  The returned value has
+   * zeros in all bit positions higher than [width].
+   *
+   * ```
+   * new BigInt.from(-1).toUnsigned(5) == 31   // 11111111  ->  00011111
+   * ```
+   *
+   * This operation can be used to simulate arithmetic from low level languages.
+   * For example, to increment an 8 bit quantity:
+   *
+   * ```
+   * q = (q + 1).toUnsigned(8);
+   * ```
+   *
+   * `q` will count from `0` up to `255` and then wrap around to `0`.
+   *
+   * If the input fits in [width] bits without truncation, the result is the
+   * same as the input.  The minimum width needed to avoid truncation of `x` is
+   * given by `x.bitLength`, i.e.
+   *
+   * ```
+   * x == x.toUnsigned(x.bitLength);
+   * ```
+   */
+  _BigIntImpl toUnsigned(int width) {
+    return this & ((one << width) - one);
+  }
+
+  /**
+   * Returns the least significant [width] bits of this integer, extending the
+   * highest retained bit to the sign.  This is the same as truncating the value
+   * to fit in [width] bits using an signed 2-s complement representation.  The
+   * returned value has the same bit value in all positions higher than [width].
+   *
+   * ```
+   * var big15 = new BigInt.from(15);
+   * var big16 = new BigInt.from(16);
+   * var big239 = new BigInt.from(239);
+   *                                      V--sign bit-V
+   * big16.toSigned(5) == -big16   //  00010000 -> 11110000
+   * big239.toSigned(5) == big15   //  11101111 -> 00001111
+   *                                      ^           ^
+   * ```
+   *
+   * This operation can be used to simulate arithmetic from low level languages.
+   * For example, to increment an 8 bit signed quantity:
+   *
+   * ```
+   * q = (q + 1).toSigned(8);
+   * ```
+   *
+   * `q` will count from `0` up to `127`, wrap to `-128` and count back up to
+   * `127`.
+   *
+   * If the input value fits in [width] bits without truncation, the result is
+   * the same as the input.  The minimum width needed to avoid truncation of `x`
+   * is `x.bitLength + 1`, i.e.
+   *
+   * ```
+   * x == x.toSigned(x.bitLength + 1);
+   * ```
+   */
+  _BigIntImpl toSigned(int width) {
+    // The value of binary number weights each bit by a power of two.  The
+    // twos-complement value weights the sign bit negatively.  We compute the
+    // value of the negative weighting by isolating the sign bit with the
+    // correct power of two weighting and subtracting it from the value of the
+    // lower bits.
+    var signMask = one << (width - 1);
+    return (this & (signMask - one)) - (this & signMask);
+  }
+
+  bool get isValidInt {
+    assert(_digitBits == 32);
+    return _used < 2 ||
+        (_used == 2 &&
+            (_digits[1] < 0x80000000 ||
+                (_isNegative && _digits[1] == 0x80000000 && _digits[0] == 0)));
+  }
+
+  int toInt() {
+    assert(_digitBits == 32);
+    if (_used == 0) return 0;
+    if (_used == 1) return _isNegative ? -_digits[0] : _digits[0];
+    if (_used == 2 && _digits[1] < 0x80000000) {
+      var result = (_digits[1] << _digitBits) | _digits[0];
+      return _isNegative ? -result : result;
+    }
+    return _isNegative ? _minInt : _maxInt;
+  }
+
+  /**
+   * Returns this [_BigIntImpl] as a [double].
+   *
+   * If the number is not representable as a [double], an
+   * approximation is returned. For numerically large integers, the
+   * approximation may be infinite.
+   */
+  double toDouble() {
+    const int exponentBias = 1075;
+    // There are 11 bits for the exponent.
+    // 2047 (all bits set to 1) is reserved for infinity and NaN.
+    // When storing the exponent in the 11 bits, it is biased by exponentBias
+    // to support negative exponents.
+    const int maxDoubleExponent = 2046 - exponentBias;
+    if (_isZero) return 0.0;
+
+    // We fill the 53 bits little-endian.
+    var resultBits = new Uint8List(8);
+
+    var length = _digitBits * (_used - 1) + _digits[_used - 1].bitLength;
+    if (length > maxDoubleExponent + 53) {
+      return _isNegative ? double.negativeInfinity : double.infinity;
+    }
+
+    // The most significant bit is for the sign.
+    if (_isNegative) resultBits[7] = 0x80;
+
+    // Write the exponent into bits 1..12:
+    var biasedExponent = length - 53 + exponentBias;
+    resultBits[6] = (biasedExponent & 0xF) << 4;
+    resultBits[7] |= biasedExponent >> 4;
+
+    int cachedBits = 0;
+    int cachedBitsLength = 0;
+    int digitIndex = _used - 1;
+    int readBits(int n) {
+      // Ensure that we have enough bits in [cachedBits].
+      while (cachedBitsLength < n) {
+        int nextDigit;
+        int nextDigitLength = _digitBits; // May get updated.
+        if (digitIndex < 0) {
+          nextDigit = 0;
+          digitIndex--;
+        } else {
+          nextDigit = _digits[digitIndex];
+          if (digitIndex == _used - 1) nextDigitLength = nextDigit.bitLength;
+          digitIndex--;
+        }
+        cachedBits = (cachedBits << nextDigitLength) + nextDigit;
+        cachedBitsLength += nextDigitLength;
+      }
+      // Read the top [n] bits.
+      var result = cachedBits >> (cachedBitsLength - n);
+      // Remove the bits from the cache.
+      cachedBits -= result << (cachedBitsLength - n);
+      cachedBitsLength -= n;
+      return result;
+    }
+
+    // The first leading 1 bit is implicit in the double-representation and can
+    // be discarded.
+    var leadingBits = readBits(5) & 0xF;
+    resultBits[6] |= leadingBits;
+
+    for (int i = 5; i >= 0; i--) {
+      // Get the remaining 48 bits.
+      resultBits[i] = readBits(8);
+    }
+
+    void roundUp() {
+      // Simply consists of adding 1 to the whole 64 bit "number".
+      // It will update the exponent, if necessary.
+      // It might even round up to infinity (which is what we want).
+      var carry = 1;
+      for (int i = 0; i < 8; i++) {
+        if (carry == 0) break;
+        var sum = resultBits[i] + carry;
+        resultBits[i] = sum & 0xFF;
+        carry = sum >> 8;
+      }
+    }
+
+    if (readBits(1) == 1) {
+      if (resultBits[0].isOdd) {
+        // Rounds to even all the time.
+        roundUp();
+      } else {
+        // Round up, if there is at least one other digit that is not 0.
+        if (cachedBits != 0) {
+          // There is already one in the cachedBits.
+          roundUp();
+        } else {
+          for (int i = digitIndex; digitIndex >= 0; i--) {
+            if (_digits[i] != 0) {
+              roundUp();
+              break;
+            }
+          }
+        }
+      }
+    }
+    return resultBits.buffer.asByteData().getFloat64(0, Endian.little);
+  }
+
+  /**
+   * Returns a String-representation of this integer.
+   *
+   * The returned string is parsable by [parse].
+   * For any `_BigIntImpl` `i`, it is guaranteed that
+   * `i == _BigIntImpl.parse(i.toString())`.
+   */
+  String toString() {
+    if (_used == 0) return "0";
+    if (_used == 1) {
+      if (_isNegative) return (-_digits[0]).toString();
+      return _digits[0].toString();
+    }
+
+    // Generate in chunks of 9 digits.
+    // The chunks are in reversed order.
+    var decimalDigitChunks = <String>[];
+    var rest = isNegative ? -this : this;
+    while (rest._used > 1) {
+      var digits9 = rest.remainder(_oneBillion).toString();
+      decimalDigitChunks.add(digits9);
+      var zeros = 9 - digits9.length;
+      if (zeros == 8) {
+        decimalDigitChunks.add("00000000");
+      } else {
+        if (zeros >= 4) {
+          zeros -= 4;
+          decimalDigitChunks.add("0000");
+        }
+        if (zeros >= 2) {
+          zeros -= 2;
+          decimalDigitChunks.add("00");
+        }
+        if (zeros >= 1) {
+          decimalDigitChunks.add("0");
+        }
+      }
+      rest = rest ~/ _oneBillion;
+    }
+    decimalDigitChunks.add(rest._digits[0].toString());
+    if (_isNegative) decimalDigitChunks.add("-");
+    return decimalDigitChunks.reversed.join();
+  }
+
+  int _toRadixCodeUnit(int digit) {
+    const int _0 = 48;
+    const int _a = 97;
+    if (digit < 10) return _0 + digit;
+    return _a + digit - 10;
+  }
+
+  /**
+   * Converts [this] to a string representation in the given [radix].
+   *
+   * In the string representation, lower-case letters are used for digits above
+   * '9', with 'a' being 10 an 'z' being 35.
+   *
+   * The [radix] argument must be an integer in the range 2 to 36.
+   */
+  String toRadixString(int radix) {
+    if (radix > 36) throw new RangeError.range(radix, 2, 36);
+
+    if (_used == 0) return "0";
+
+    if (_used == 1) {
+      var digitString = _digits[0].toRadixString(radix);
+      if (_isNegative) return "-" + digitString;
+      return digitString;
+    }
+
+    if (radix == 16) return _toHexString();
+
+    var base = new _BigIntImpl._fromInt(radix);
+    var reversedDigitCodeUnits = <int>[];
+    var rest = this.abs();
+    while (!rest._isZero) {
+      var digit = rest.remainder(base).toInt();
+      rest = rest ~/ base;
+      reversedDigitCodeUnits.add(_toRadixCodeUnit(digit));
+    }
+    var digitString = new String.fromCharCodes(reversedDigitCodeUnits.reversed);
+    if (_isNegative) return "-" + digitString;
+    return digitString;
+  }
+
+  String _toHexString() {
+    var chars = <int>[];
+    for (int i = 0; i < _used - 1; i++) {
+      int chunk = _digits[i];
+      for (int j = 0; j < (_digitBits ~/ 4); j++) {
+        chars.add(_toRadixCodeUnit(chunk & 0xF));
+        chunk >>= 4;
+      }
+    }
+    var msbChunk = _digits[_used - 1];
+    while (msbChunk != 0) {
+      chars.add(_toRadixCodeUnit(msbChunk & 0xF));
+      msbChunk >>= 4;
+    }
+    if (_isNegative) {
+      const _dash = 45;
+      chars.add(_dash);
+    }
+    return new String.fromCharCodes(chars.reversed);
+  }
+}
+
+// Interface for modular reduction.
+abstract class _BigIntReduction {
+  int get _normModulusUsed;
+  // Return the number of digits used by resultDigits.
+  int _convert(_BigIntImpl x, Uint32List resultDigits);
+  int _mul(Uint32List xDigits, int xUsed, Uint32List yDigits, int yUsed,
+      Uint32List resultDigits);
+  int _sqr(Uint32List xDigits, int xUsed, Uint32List resultDigits);
+
+  // Return x reverted to _BigIntImpl.
+  _BigIntImpl _revert(Uint32List xDigits, int xUsed);
+}
+
+// Montgomery reduction on _BigIntImpl.
+class _BigIntMontgomeryReduction implements _BigIntReduction {
+  final _BigIntImpl _modulus;
+  int _normModulusUsed; // Even if processing 64-bit (digit pairs).
+  Uint32List _modulusDigits;
+  Uint32List _args;
+  int _digitsPerStep; // Number of digits processed in one step. 1 or 2.
+  static const int _xDigit = 0; // Index of digit of x.
+  static const int _xHighDigit = 1; // Index of high digit of x (64-bit only).
+  static const int _rhoDigit = 2; // Index of digit of rho.
+  static const int _rhoHighDigit = 3; // Index of high digit of rho (64-bit).
+  static const int _muDigit = 4; // Index of mu.
+  static const int _muHighDigit = 5; // Index of high 32-bits of mu (64-bit).
+
+  _BigIntMontgomeryReduction(this._modulus) {
+    _modulusDigits = _modulus._digits;
+    _args = _newDigits(6);
+    // Determine if we can process digit pairs by calling an intrinsic.
+    _digitsPerStep = _mulMod(_args, _args, 0);
+    _args[_xDigit] = _modulusDigits[0];
+    if (_digitsPerStep == 1) {
+      _normModulusUsed = _modulus._used;
+      _invDigit(_args);
+    } else {
+      assert(_digitsPerStep == 2);
+      _normModulusUsed = _modulus._used + (_modulus._used & 1);
+      _args[_xHighDigit] = _modulusDigits[1];
+      _invDigitPair(_args);
+    }
+  }
+
+  // Calculates -1/x % _digitBase, x is 32-bit digit.
+  //         xy == 1 (mod m)
+  //         xy =  1+km
+  //   xy(2-xy) = (1+km)(1-km)
+  // x(y(2-xy)) = 1-k^2 m^2
+  // x(y(2-xy)) == 1 (mod m^2)
+  // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
+  // Should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
+  //
+  // Operation:
+  //   args[_rhoDigit] = 1/args[_xDigit] mod _digitBase.
+  static void _invDigit(Uint32List args) {
+    var x = args[_xDigit];
+    var y = x & 3; // y == 1/x mod 2^2
+    y = (y * (2 - (x & 0xf) * y)) & 0xf; // y == 1/x mod 2^4
+    y = (y * (2 - (x & 0xff) * y)) & 0xff; // y == 1/x mod 2^8
+    y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16
+    y = (y * (2 - x * y % _BigIntImpl._digitBase)) % _BigIntImpl._digitBase;
+    // y == 1/x mod _digitBase
+    y = -y; // We really want the negative inverse.
+    args[_rhoDigit] = y & _BigIntImpl._digitMask;
+    assert(((x * y) & _BigIntImpl._digitMask) == _BigIntImpl._digitMask);
+  }
+
+  // Calculates -1/x % _digitBase^2, x is a pair of 32-bit digits.
+  // Operation:
+  //   args[_rhoDigit.._rhoHighDigit] =
+  //     1/args[_xDigit.._xHighDigit] mod _digitBase^2.
+  static void _invDigitPair(Uint32List args) {
+    var xl = args[_xDigit]; // Lower 32-bit digit of x.
+    var y = xl & 3; // y == 1/x mod 2^2
+    y = (y * (2 - (xl & 0xf) * y)) & 0xf; // y == 1/x mod 2^4
+    y = (y * (2 - (xl & 0xff) * y)) & 0xff; // y == 1/x mod 2^8
+    y = (y * (2 - (((xl & 0xffff) * y) & 0xffff))) & 0xffff;
+    // y == 1/x mod 2^16
+    y = (y * (2 - ((xl * y) & 0xffffffff))) & 0xffffffff; // y == 1/x mod 2^32
+    var x = (args[_xHighDigit] << _BigIntImpl._digitBits) | xl;
+    y *= 2 - x * y; // Masking with 2^64-1 is implied by 64-bit arithmetic.
+    // y == 1/x mod _digitBase^2
+    y = -y; // We really want the negative inverse.
+    args[_rhoDigit] = y & _BigIntImpl._digitMask;
+    args[_rhoHighDigit] =
+        (y >> _BigIntImpl._digitBits) & _BigIntImpl._digitMask;
+    assert(x * y == -1);
+  }
+
+  // Operation:
+  //   args[_muDigit] = args[_rhoDigit]*digits[i] mod _digitBase.
+  //   Returns 1.
+  // Note: Intrinsics on 64-bit platforms process digit pairs at even indices:
+  //   args[_muDigit.._muHighDigit] =
+  //     args[_rhoDigit.._rhoHighDigit] * digits[i..i+1] mod _digitBase^2.
+  //   Returns 2.
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  @pragma("vm:never-inline")
+  static int _mulMod(Uint32List args, Uint32List digits, int i) {
+    var rhol = args[_rhoDigit] & _BigIntImpl._halfDigitMask;
+    var rhoh = args[_rhoDigit] >> _BigIntImpl._halfDigitBits;
+    var dh = digits[i] >> _BigIntImpl._halfDigitBits;
+    var dl = digits[i] & _BigIntImpl._halfDigitMask;
+    args[_muDigit] = (dl * rhol +
+            (((dl * rhoh + dh * rhol) & _BigIntImpl._halfDigitMask) <<
+                _BigIntImpl._halfDigitBits)) &
+        _BigIntImpl._digitMask;
+    return 1;
+  }
+
+  // result = x*R mod _modulus.
+  // Returns resultUsed.
+  int _convert(_BigIntImpl x, Uint32List resultDigits) {
+    // Montgomery reduction only works if abs(x) < _modulus.
+    assert(x.abs() < _modulus);
+    assert(_digitsPerStep == 1 || _normModulusUsed.isEven);
+    var result = x.abs()._dlShift(_normModulusUsed)._rem(_modulus);
+    if (x._isNegative && !result._isNegative && result._used > 0) {
+      result = _modulus - result;
+    }
+    var used = result._used;
+    var digits = result._digits;
+    var i = used + (used & 1);
+    while (--i >= 0) {
+      resultDigits[i] = digits[i];
+    }
+    return used;
+  }
+
+  _BigIntImpl _revert(Uint32List xDigits, int xUsed) {
+    // Reserve enough digits for modulus squaring and accumulator carry.
+    var resultDigits = _newDigits(2 * _normModulusUsed + 2);
+    var i = xUsed + (xUsed & 1);
+    while (--i >= 0) {
+      resultDigits[i] = xDigits[i];
+    }
+    var resultUsed = _reduce(resultDigits, xUsed);
+    return new _BigIntImpl._(false, resultUsed, resultDigits);
+  }
+
+  // x = x/R mod _modulus.
+  // Returns xUsed.
+  int _reduce(Uint32List xDigits, int xUsed) {
+    while (xUsed < 2 * _normModulusUsed + 2) {
+      // Pad x so _mulAdd has enough room later for a possible carry.
+      xDigits[xUsed++] = 0;
+    }
+    var i = 0;
+    while (i < _normModulusUsed) {
+      var d = _mulMod(_args, xDigits, i);
+      assert(d == _digitsPerStep);
+      d = _BigIntImpl._mulAdd(
+          _args, _muDigit, _modulusDigits, 0, xDigits, i, _normModulusUsed);
+      assert(d == _digitsPerStep);
+      i += d;
+    }
+    // Clamp x.
+    while (xUsed > 0 && xDigits[xUsed - 1] == 0) {
+      --xUsed;
+    }
+    xUsed = _BigIntImpl._drShiftDigits(xDigits, xUsed, i, xDigits);
+    if (_BigIntImpl._compareDigits(
+            xDigits, xUsed, _modulusDigits, _normModulusUsed) >=
+        0) {
+      _BigIntImpl._absSub(
+          xDigits, xUsed, _modulusDigits, _normModulusUsed, xDigits);
+    }
+    // Clamp x.
+    while (xUsed > 0 && xDigits[xUsed - 1] == 0) {
+      --xUsed;
+    }
+    return xUsed;
+  }
+
+  int _sqr(Uint32List xDigits, int xUsed, Uint32List resultDigits) {
+    var resultUsed = _BigIntImpl._sqrDigits(xDigits, xUsed, resultDigits);
+    return _reduce(resultDigits, resultUsed);
+  }
+
+  int _mul(Uint32List xDigits, int xUsed, Uint32List yDigits, int yUsed,
+      Uint32List resultDigits) {
+    var resultUsed =
+        _BigIntImpl._mulDigits(xDigits, xUsed, yDigits, yUsed, resultDigits);
+    return _reduce(resultDigits, resultUsed);
+  }
+}
+
+// Modular reduction using "classic" algorithm.
+class _BigIntClassicReduction implements _BigIntReduction {
+  final _BigIntImpl _modulus; // Modulus.
+  int _normModulusUsed;
+  _BigIntImpl _normModulus; // Normalized _modulus.
+  Uint32List _normModulusDigits;
+  Uint32List _negNormModulusDigits; // Negated _normModulus digits.
+  int _modulusNsh; // Normalization shift amount.
+  Uint32List _args; // Top _normModulus digit(s) and place holder for estimated
+  // quotient digit(s).
+  Uint32List _tmpDigits; // Temporary digits used during reduction.
+
+  _BigIntClassicReduction(this._modulus) {
+    // Preprocess arguments to _remDigits.
+    var nsh =
+        _BigIntImpl._digitBits - _modulus._digits[_modulus._used - 1].bitLength;
+    // For 64-bit processing, make sure _negNormModulusDigits has an even number
+    // of digits.
+    if (_modulus._used.isOdd) {
+      nsh += _BigIntImpl._digitBits;
+    }
+    _modulusNsh = nsh;
+    _normModulus = _modulus << nsh;
+    _normModulusUsed = _normModulus._used;
+    _normModulusDigits = _normModulus._digits;
+    assert(_normModulusUsed.isEven);
+    _args = _newDigits(4);
+    _args[_BigIntImpl._divisorLowTopDigit] =
+        _normModulusDigits[_normModulusUsed - 2];
+    _args[_BigIntImpl._divisorTopDigit] =
+        _normModulusDigits[_normModulusUsed - 1];
+    // Negate _normModulus so we can use _mulAdd instead of
+    // unimplemented  _mulSub.
+    var negNormModulus =
+        _BigIntImpl.one._dlShift(_normModulusUsed) - _normModulus;
+    if (negNormModulus._used < _normModulusUsed) {
+      _negNormModulusDigits = _BigIntImpl._cloneDigits(
+          negNormModulus._digits, 0, _normModulusUsed, _normModulusUsed);
+    } else {
+      _negNormModulusDigits = negNormModulus._digits;
+    }
+    // _negNormModulusDigits is read-only and has _normModulusUsed digits (possibly
+    // including several leading zeros) plus a leading zero for 64-bit
+    // processing.
+    _tmpDigits = _newDigits(2 * _normModulusUsed);
+  }
+
+  int _convert(_BigIntImpl x, Uint32List resultDigits) {
+    var digits;
+    var used;
+    if (x._isNegative || x._absCompare(_modulus) >= 0) {
+      var remainder = x._rem(_modulus);
+      if (x._isNegative && remainder._used > 0) {
+        assert(remainder._isNegative);
+        remainder += _modulus;
+      }
+      assert(!remainder._isNegative);
+      used = remainder._used;
+      digits = remainder._digits;
+    } else {
+      used = x._used;
+      digits = x._digits;
+    }
+    var i = used + (used & 1); // Copy leading zero if any.
+    while (--i >= 0) {
+      resultDigits[i] = digits[i];
+    }
+    return used;
+  }
+
+  _BigIntImpl _revert(Uint32List xDigits, int xUsed) {
+    return new _BigIntImpl._(false, xUsed, xDigits);
+  }
+
+  int _reduce(Uint32List xDigits, int xUsed) {
+    if (xUsed < _modulus._used) {
+      return xUsed;
+    }
+    // The function _BigIntImpl._remDigits(...) is optimized for reduction and
+    // equivalent to calling
+    // 'convert(revert(xDigits, xUsed)._rem(_normModulus), xDigits);'
+    return _BigIntImpl._remDigits(
+        xDigits,
+        xUsed,
+        _normModulusDigits,
+        _normModulusUsed,
+        _negNormModulusDigits,
+        _modulusNsh,
+        _args,
+        _tmpDigits,
+        xDigits);
+  }
+
+  int _sqr(Uint32List xDigits, int xUsed, Uint32List resultDigits) {
+    var resultUsed = _BigIntImpl._sqrDigits(xDigits, xUsed, resultDigits);
+    return _reduce(resultDigits, resultUsed);
+  }
+
+  int _mul(Uint32List xDigits, int xUsed, Uint32List yDigits, int yUsed,
+      Uint32List resultDigits) {
+    var resultUsed =
+        _BigIntImpl._mulDigits(xDigits, xUsed, yDigits, yUsed, resultDigits);
+    return _reduce(resultDigits, resultUsed);
+  }
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/bool_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/bool_patch.dart
new file mode 100644
index 0000000..7c20001
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/bool_patch.dart
@@ -0,0 +1,20 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+@patch
+@pragma("vm:entry-point")
+class bool {
+  @patch
+  const factory bool.fromEnvironment(String name, {bool defaultValue: false})
+      native "Bool_fromEnvironment";
+
+  @patch
+  int get hashCode => this ? 1231 : 1237;
+
+  int get _identityHashCode => this ? 1231 : 1237;
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/class_id.dart b/sdk_nnbd/lib/_internal/vm/lib/class_id.dart
new file mode 100644
index 0000000..478ade5
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/class_id.dart
@@ -0,0 +1,16 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "internal_patch.dart";
+
+@pragma("vm:entry-point")
+class ClassID {
+  @pragma("vm:entry-point")
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  static int getID(Object value) native "ClassID_getID";
+
+  // VM injects class id constants into this class.
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/class_id_fasta.dart b/sdk_nnbd/lib/_internal/vm/lib/class_id_fasta.dart
new file mode 100644
index 0000000..1dbb2b3
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/class_id_fasta.dart
@@ -0,0 +1,29 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "internal_patch.dart";
+
+@pragma("vm:entry-point")
+class ClassID {
+  @pragma("vm:entry-point", "call")
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  static int getID(Object value) native "ClassID_getID";
+
+  @pragma("vm:entry-point")
+  static final int cidArray = 0;
+  @pragma("vm:entry-point")
+  static final int cidExternalOneByteString = 0;
+  @pragma("vm:entry-point")
+  static final int cidGrowableObjectArray = 0;
+  @pragma("vm:entry-point")
+  static final int cidImmutableArray = 0;
+  @pragma("vm:entry-point")
+  static final int cidOneByteString = 0;
+  @pragma("vm:entry-point")
+  static final int cidTwoByteString = 0;
+  @pragma("vm:entry-point")
+  static final int cidUint8ArrayView = 0;
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/collection_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/collection_patch.dart
new file mode 100644
index 0000000..b421d7d
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/collection_patch.dart
@@ -0,0 +1,940 @@
+// 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
+
+/// Note: the VM concatenates all patch files into a single patch file. This
+/// file is the first patch in "dart:collection" which contains all the imports
+/// used by patches of that library. We plan to change this when we have a
+/// shared front end and simply use parts.
+
+import "dart:_internal" as internal;
+
+import "dart:_internal" show patch, IterableElementError;
+
+import "dart:typed_data" show Uint32List;
+
+/// These are the additional parts of this patch library:
+// part "compact_hash.dart";
+
+@patch
+class HashMap<K, V> {
+  @patch
+  factory HashMap(
+      {bool equals(K key1, K key2),
+      int hashCode(K key),
+      bool isValidKey(potentialKey)}) {
+    if (isValidKey == null) {
+      if (hashCode == null) {
+        if (equals == null) {
+          return new _HashMap<K, V>();
+        }
+        hashCode = _defaultHashCode;
+      } else {
+        if (identical(identityHashCode, hashCode) &&
+            identical(identical, equals)) {
+          return new _IdentityHashMap<K, V>();
+        }
+        equals ??= _defaultEquals;
+      }
+    } else {
+      hashCode ??= _defaultHashCode;
+      equals ??= _defaultEquals;
+    }
+    return new _CustomHashMap<K, V>(equals, hashCode, isValidKey);
+  }
+
+  @patch
+  factory HashMap.identity() => new _IdentityHashMap<K, V>();
+
+  Set<K> _newKeySet();
+}
+
+const int _MODIFICATION_COUNT_MASK = 0x3fffffff;
+
+class _HashMap<K, V> extends MapBase<K, V> implements HashMap<K, V> {
+  static const int _INITIAL_CAPACITY = 8;
+
+  int _elementCount = 0;
+  List<_HashMapEntry<K, V>> _buckets =
+      new List<_HashMapEntry<K, V>>(_INITIAL_CAPACITY);
+  int _modificationCount = 0;
+
+  int get length => _elementCount;
+  bool get isEmpty => _elementCount == 0;
+  bool get isNotEmpty => _elementCount != 0;
+
+  Iterable<K> get keys => new _HashMapKeyIterable<K, V>(this);
+  Iterable<V> get values => new _HashMapValueIterable<K, V>(this);
+
+  bool containsKey(Object key) {
+    final hashCode = key.hashCode;
+    final buckets = _buckets;
+    final index = hashCode & (buckets.length - 1);
+    var entry = buckets[index];
+    while (entry != null) {
+      if (hashCode == entry.hashCode && entry.key == key) return true;
+      entry = entry.next;
+    }
+    return false;
+  }
+
+  bool containsValue(Object value) {
+    final buckets = _buckets;
+    final length = buckets.length;
+    for (int i = 0; i < length; i++) {
+      var entry = buckets[i];
+      while (entry != null) {
+        if (entry.value == value) return true;
+        entry = entry.next;
+      }
+    }
+    return false;
+  }
+
+  V operator [](Object key) {
+    final hashCode = key.hashCode;
+    final buckets = _buckets;
+    final index = hashCode & (buckets.length - 1);
+    var entry = buckets[index];
+    while (entry != null) {
+      if (hashCode == entry.hashCode && entry.key == key) {
+        return entry.value;
+      }
+      entry = entry.next;
+    }
+    return null;
+  }
+
+  void operator []=(K key, V value) {
+    final hashCode = key.hashCode;
+    final buckets = _buckets;
+    final length = buckets.length;
+    final index = hashCode & (length - 1);
+    var entry = buckets[index];
+    while (entry != null) {
+      if (hashCode == entry.hashCode && entry.key == key) {
+        entry.value = value;
+        return;
+      }
+      entry = entry.next;
+    }
+    _addEntry(buckets, index, length, key, value, hashCode);
+  }
+
+  V putIfAbsent(K key, V ifAbsent()) {
+    final hashCode = key.hashCode;
+    final buckets = _buckets;
+    final length = buckets.length;
+    final index = hashCode & (length - 1);
+    var entry = buckets[index];
+    while (entry != null) {
+      if (hashCode == entry.hashCode && entry.key == key) {
+        return entry.value;
+      }
+      entry = entry.next;
+    }
+    final stamp = _modificationCount;
+    final V value = ifAbsent();
+    if (stamp == _modificationCount) {
+      _addEntry(buckets, index, length, key, value, hashCode);
+    } else {
+      this[key] = value;
+    }
+    return value;
+  }
+
+  void addAll(Map<K, V> other) {
+    other.forEach((K key, V value) {
+      this[key] = value;
+    });
+  }
+
+  void forEach(void action(K key, V value)) {
+    final stamp = _modificationCount;
+    final buckets = _buckets;
+    final length = buckets.length;
+    for (int i = 0; i < length; i++) {
+      var entry = buckets[i];
+      while (entry != null) {
+        action(entry.key, entry.value);
+        if (stamp != _modificationCount) {
+          throw new ConcurrentModificationError(this);
+        }
+        entry = entry.next;
+      }
+    }
+  }
+
+  V remove(Object key) {
+    final hashCode = key.hashCode;
+    final buckets = _buckets;
+    final index = hashCode & (buckets.length - 1);
+    var entry = buckets[index];
+    _HashMapEntry<K, V> previous = null;
+    while (entry != null) {
+      final next = entry.next;
+      if (hashCode == entry.hashCode && entry.key == key) {
+        _removeEntry(entry, previous, index);
+        _elementCount--;
+        _modificationCount =
+            (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
+        return entry.value;
+      }
+      previous = entry;
+      entry = next;
+    }
+    return null;
+  }
+
+  void clear() {
+    _buckets = new List(_INITIAL_CAPACITY);
+    if (_elementCount > 0) {
+      _elementCount = 0;
+      _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
+    }
+  }
+
+  void _removeEntry(_HashMapEntry<K, V> entry,
+      _HashMapEntry<K, V> previousInBucket, int bucketIndex) {
+    if (previousInBucket == null) {
+      _buckets[bucketIndex] = entry.next;
+    } else {
+      previousInBucket.next = entry.next;
+    }
+  }
+
+  void _addEntry(List<_HashMapEntry<K, V>> buckets, int index, int length,
+      K key, V value, int hashCode) {
+    final entry = new _HashMapEntry<K, V>(key, value, hashCode, buckets[index]);
+    buckets[index] = entry;
+    final newElements = _elementCount + 1;
+    _elementCount = newElements;
+    // If we end up with more than 75% non-empty entries, we
+    // resize the backing store.
+    if ((newElements << 2) > ((length << 1) + length)) _resize();
+    _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
+  }
+
+  void _resize() {
+    final oldBuckets = _buckets;
+    final oldLength = oldBuckets.length;
+    final newLength = oldLength << 1;
+    final newBuckets = new List<_HashMapEntry<K, V>>(newLength);
+    for (int i = 0; i < oldLength; i++) {
+      var entry = oldBuckets[i];
+      while (entry != null) {
+        final next = entry.next;
+        final hashCode = entry.hashCode;
+        final index = hashCode & (newLength - 1);
+        entry.next = newBuckets[index];
+        newBuckets[index] = entry;
+        entry = next;
+      }
+    }
+    _buckets = newBuckets;
+  }
+
+  Set<K> _newKeySet() => new _HashSet<K>();
+}
+
+class _CustomHashMap<K, V> extends _HashMap<K, V> {
+  final _Equality<K> _equals;
+  final _Hasher<K> _hashCode;
+  final _Predicate _validKey;
+  _CustomHashMap(this._equals, this._hashCode, validKey)
+      : _validKey = (validKey != null) ? validKey : new _TypeTest<K>().test;
+
+  bool containsKey(Object key) {
+    if (!_validKey(key)) return false;
+    final hashCode = _hashCode(key);
+    final buckets = _buckets;
+    final index = hashCode & (buckets.length - 1);
+    var entry = buckets[index];
+    while (entry != null) {
+      if (hashCode == entry.hashCode && _equals(entry.key, key)) return true;
+      entry = entry.next;
+    }
+    return false;
+  }
+
+  V operator [](Object key) {
+    if (!_validKey(key)) return null;
+    final hashCode = _hashCode(key);
+    final buckets = _buckets;
+    final index = hashCode & (buckets.length - 1);
+    var entry = buckets[index];
+    while (entry != null) {
+      if (hashCode == entry.hashCode && _equals(entry.key, key)) {
+        return entry.value;
+      }
+      entry = entry.next;
+    }
+    return null;
+  }
+
+  void operator []=(K key, V value) {
+    final hashCode = _hashCode(key);
+    final buckets = _buckets;
+    final length = buckets.length;
+    final index = hashCode & (length - 1);
+    var entry = buckets[index];
+    while (entry != null) {
+      if (hashCode == entry.hashCode && _equals(entry.key, key)) {
+        entry.value = value;
+        return;
+      }
+      entry = entry.next;
+    }
+    _addEntry(buckets, index, length, key, value, hashCode);
+  }
+
+  V putIfAbsent(K key, V ifAbsent()) {
+    final hashCode = _hashCode(key);
+    final buckets = _buckets;
+    final length = buckets.length;
+    final index = hashCode & (length - 1);
+    var entry = buckets[index];
+    while (entry != null) {
+      if (hashCode == entry.hashCode && _equals(entry.key, key)) {
+        return entry.value;
+      }
+      entry = entry.next;
+    }
+    int stamp = _modificationCount;
+    V value = ifAbsent();
+    if (stamp == _modificationCount) {
+      _addEntry(buckets, index, length, key, value, hashCode);
+    } else {
+      this[key] = value;
+    }
+    return value;
+  }
+
+  V remove(Object key) {
+    if (!_validKey(key)) return null;
+    final hashCode = _hashCode(key);
+    final buckets = _buckets;
+    final index = hashCode & (buckets.length - 1);
+    var entry = buckets[index];
+    _HashMapEntry<K, V> previous = null;
+    while (entry != null) {
+      final next = entry.next;
+      if (hashCode == entry.hashCode && _equals(entry.key, key)) {
+        _removeEntry(entry, previous, index);
+        _elementCount--;
+        _modificationCount =
+            (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
+        return entry.value;
+      }
+      previous = entry;
+      entry = next;
+    }
+    return null;
+  }
+
+  Set<K> _newKeySet() => new _CustomHashSet<K>(_equals, _hashCode, _validKey);
+}
+
+class _IdentityHashMap<K, V> extends _HashMap<K, V> {
+  bool containsKey(Object key) {
+    final hashCode = identityHashCode(key);
+    final buckets = _buckets;
+    final index = hashCode & (buckets.length - 1);
+    var entry = buckets[index];
+    while (entry != null) {
+      if (hashCode == entry.hashCode && identical(entry.key, key)) return true;
+      entry = entry.next;
+    }
+    return false;
+  }
+
+  V operator [](Object key) {
+    final hashCode = identityHashCode(key);
+    final buckets = _buckets;
+    final index = hashCode & (buckets.length - 1);
+    var entry = buckets[index];
+    while (entry != null) {
+      if (hashCode == entry.hashCode && identical(entry.key, key)) {
+        return entry.value;
+      }
+      entry = entry.next;
+    }
+    return null;
+  }
+
+  void operator []=(K key, V value) {
+    final hashCode = identityHashCode(key);
+    final buckets = _buckets;
+    final length = buckets.length;
+    final index = hashCode & (length - 1);
+    var entry = buckets[index];
+    while (entry != null) {
+      if (hashCode == entry.hashCode && identical(entry.key, key)) {
+        entry.value = value;
+        return;
+      }
+      entry = entry.next;
+    }
+    _addEntry(buckets, index, length, key, value, hashCode);
+  }
+
+  V putIfAbsent(K key, V ifAbsent()) {
+    final hashCode = identityHashCode(key);
+    final buckets = _buckets;
+    final length = buckets.length;
+    final index = hashCode & (length - 1);
+    var entry = buckets[index];
+    while (entry != null) {
+      if (hashCode == entry.hashCode && identical(entry.key, key)) {
+        return entry.value;
+      }
+      entry = entry.next;
+    }
+    final stamp = _modificationCount;
+    V value = ifAbsent();
+    if (stamp == _modificationCount) {
+      _addEntry(buckets, index, length, key, value, hashCode);
+    } else {
+      this[key] = value;
+    }
+    return value;
+  }
+
+  V remove(Object key) {
+    final hashCode = identityHashCode(key);
+    final buckets = _buckets;
+    final index = hashCode & (buckets.length - 1);
+    var entry = buckets[index];
+    _HashMapEntry<K, V> previous = null;
+    while (entry != null) {
+      final next = entry.next;
+      if (hashCode == entry.hashCode && identical(entry.key, key)) {
+        _removeEntry(entry, previous, index);
+        _elementCount--;
+        _modificationCount =
+            (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
+        return entry.value;
+      }
+      previous = entry;
+      entry = next;
+    }
+    return null;
+  }
+
+  Set<K> _newKeySet() => new _IdentityHashSet<K>();
+}
+
+class _HashMapEntry<K, V> {
+  final K key;
+  V value;
+  final int hashCode;
+  _HashMapEntry<K, V> next;
+  _HashMapEntry(this.key, this.value, this.hashCode, this.next);
+}
+
+abstract class _HashMapIterable<K, V, E>
+    extends internal.EfficientLengthIterable<E> {
+  final _HashMap<K, V> _map;
+  _HashMapIterable(this._map);
+  int get length => _map.length;
+  bool get isEmpty => _map.isEmpty;
+  bool get isNotEmpty => _map.isNotEmpty;
+}
+
+class _HashMapKeyIterable<K, V> extends _HashMapIterable<K, V, K> {
+  _HashMapKeyIterable(_HashMap<K, V> map) : super(map);
+  Iterator<K> get iterator => new _HashMapKeyIterator<K, V>(_map);
+  bool contains(Object key) => _map.containsKey(key);
+  void forEach(void action(K key)) {
+    _map.forEach((K key, _) {
+      action(key);
+    });
+  }
+
+  Set<K> toSet() => _map._newKeySet()..addAll(this);
+}
+
+class _HashMapValueIterable<K, V> extends _HashMapIterable<K, V, V> {
+  _HashMapValueIterable(_HashMap<K, V> map) : super(map);
+  Iterator<V> get iterator => new _HashMapValueIterator<K, V>(_map);
+  bool contains(Object value) => _map.containsValue(value);
+  void forEach(void action(V value)) {
+    _map.forEach((_, V value) {
+      action(value);
+    });
+  }
+}
+
+abstract class _HashMapIterator<K, V, E> implements Iterator<E> {
+  final _HashMap<K, V> _map;
+  final int _stamp;
+
+  int _index = 0;
+  _HashMapEntry<K, V> _entry;
+
+  _HashMapIterator(this._map) : _stamp = _map._modificationCount;
+
+  bool moveNext() {
+    if (_stamp != _map._modificationCount) {
+      throw new ConcurrentModificationError(_map);
+    }
+    var entry = _entry;
+    if (entry != null) {
+      final next = entry.next;
+      if (next != null) {
+        _entry = next;
+        return true;
+      }
+      _entry = null;
+    }
+    final buckets = _map._buckets;
+    final length = buckets.length;
+    for (int i = _index; i < length; i++) {
+      entry = buckets[i];
+      if (entry != null) {
+        _index = i + 1;
+        _entry = entry;
+        return true;
+      }
+    }
+    _index = length;
+    return false;
+  }
+}
+
+class _HashMapKeyIterator<K, V> extends _HashMapIterator<K, V, K> {
+  _HashMapKeyIterator(_HashMap<K, V> map) : super(map);
+  K get current => _entry?.key;
+}
+
+class _HashMapValueIterator<K, V> extends _HashMapIterator<K, V, V> {
+  _HashMapValueIterator(_HashMap<K, V> map) : super(map);
+  V get current => _entry?.value;
+}
+
+@patch
+class HashSet<E> {
+  @patch
+  factory HashSet(
+      {bool equals(E e1, E e2),
+      int hashCode(E e),
+      bool isValidKey(potentialKey)}) {
+    if (isValidKey == null) {
+      if (hashCode == null) {
+        if (equals == null) {
+          return new _HashSet<E>();
+        }
+        hashCode = _defaultHashCode;
+      } else {
+        if (identical(identityHashCode, hashCode) &&
+            identical(identical, equals)) {
+          return new _IdentityHashSet<E>();
+        }
+        equals ??= _defaultEquals;
+      }
+    } else {
+      hashCode ??= _defaultHashCode;
+      equals ??= _defaultEquals;
+    }
+    return new _CustomHashSet<E>(equals, hashCode, isValidKey);
+  }
+
+  @patch
+  factory HashSet.identity() => new _IdentityHashSet<E>();
+}
+
+class _HashSet<E> extends _SetBase<E> implements HashSet<E> {
+  static const int _INITIAL_CAPACITY = 8;
+
+  List<_HashSetEntry<E>> _buckets =
+      new List<_HashSetEntry<E>>(_INITIAL_CAPACITY);
+  int _elementCount = 0;
+  int _modificationCount = 0;
+
+  bool _equals(e1, e2) => e1 == e2;
+  int _hashCode(e) => e.hashCode;
+
+  static Set<R> _newEmpty<R>() => new _HashSet<R>();
+
+  // Iterable.
+
+  Iterator<E> get iterator => new _HashSetIterator<E>(this);
+
+  int get length => _elementCount;
+
+  bool get isEmpty => _elementCount == 0;
+
+  bool get isNotEmpty => _elementCount != 0;
+
+  bool contains(Object object) {
+    int index = _hashCode(object) & (_buckets.length - 1);
+    _HashSetEntry<E> entry = _buckets[index];
+    while (entry != null) {
+      if (_equals(entry.key, object)) return true;
+      entry = entry.next;
+    }
+    return false;
+  }
+
+  E lookup(Object object) {
+    int index = _hashCode(object) & (_buckets.length - 1);
+    _HashSetEntry<E> entry = _buckets[index];
+    while (entry != null) {
+      var key = entry.key;
+      if (_equals(key, object)) return key;
+      entry = entry.next;
+    }
+    return null;
+  }
+
+  E get first {
+    for (int i = 0; i < _buckets.length; i++) {
+      var entry = _buckets[i];
+      if (entry != null) {
+        return entry.key;
+      }
+    }
+    throw IterableElementError.noElement();
+  }
+
+  E get last {
+    for (int i = _buckets.length - 1; i >= 0; i--) {
+      var entry = _buckets[i];
+      if (entry != null) {
+        while (entry.next != null) {
+          entry = entry.next;
+        }
+        return entry.key;
+      }
+    }
+    throw IterableElementError.noElement();
+  }
+
+  // Set.
+
+  bool add(E element) {
+    final hashCode = _hashCode(element);
+    final index = hashCode & (_buckets.length - 1);
+    _HashSetEntry<E> entry = _buckets[index];
+    while (entry != null) {
+      if (_equals(entry.key, element)) return false;
+      entry = entry.next;
+    }
+    _addEntry(element, hashCode, index);
+    return true;
+  }
+
+  void addAll(Iterable<E> objects) {
+    for (E object in objects) {
+      add(object);
+    }
+  }
+
+  bool _remove(Object object, int hashCode) {
+    final index = hashCode & (_buckets.length - 1);
+    _HashSetEntry<E> entry = _buckets[index];
+    _HashSetEntry<E> previous = null;
+    while (entry != null) {
+      if (_equals(entry.key, object)) {
+        _HashSetEntry<E> next = entry.remove();
+        if (previous == null) {
+          _buckets[index] = next;
+        } else {
+          previous.next = next;
+        }
+        _elementCount--;
+        _modificationCount =
+            (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
+        return true;
+      }
+      previous = entry;
+      entry = entry.next;
+    }
+    return false;
+  }
+
+  bool remove(Object object) => _remove(object, _hashCode(object));
+
+  void removeAll(Iterable<Object> objectsToRemove) {
+    for (Object object in objectsToRemove) {
+      _remove(object, _hashCode(object));
+    }
+  }
+
+  void _filterWhere(bool test(E element), bool removeMatching) {
+    int length = _buckets.length;
+    for (int index = 0; index < length; index++) {
+      _HashSetEntry<E> entry = _buckets[index];
+      _HashSetEntry<E> previous = null;
+      while (entry != null) {
+        int modificationCount = _modificationCount;
+        bool testResult = test(entry.key);
+        if (modificationCount != _modificationCount) {
+          throw new ConcurrentModificationError(this);
+        }
+        if (testResult == removeMatching) {
+          _HashSetEntry<E> next = entry.remove();
+          if (previous == null) {
+            _buckets[index] = next;
+          } else {
+            previous.next = next;
+          }
+          _elementCount--;
+          _modificationCount =
+              (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
+          entry = next;
+        } else {
+          previous = entry;
+          entry = entry.next;
+        }
+      }
+    }
+  }
+
+  void removeWhere(bool test(E element)) {
+    _filterWhere(test, true);
+  }
+
+  void retainWhere(bool test(E element)) {
+    _filterWhere(test, false);
+  }
+
+  void clear() {
+    _buckets = new List(_INITIAL_CAPACITY);
+    if (_elementCount > 0) {
+      _elementCount = 0;
+      _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
+    }
+  }
+
+  void _addEntry(E key, int hashCode, int index) {
+    _buckets[index] = new _HashSetEntry<E>(key, hashCode, _buckets[index]);
+    int newElements = _elementCount + 1;
+    _elementCount = newElements;
+    int length = _buckets.length;
+    // If we end up with more than 75% non-empty entries, we
+    // resize the backing store.
+    if ((newElements << 2) > ((length << 1) + length)) _resize();
+    _modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
+  }
+
+  void _resize() {
+    int oldLength = _buckets.length;
+    int newLength = oldLength << 1;
+    List oldBuckets = _buckets;
+    List newBuckets = new List<_HashSetEntry<E>>(newLength);
+    for (int i = 0; i < oldLength; i++) {
+      _HashSetEntry<E> entry = oldBuckets[i];
+      while (entry != null) {
+        _HashSetEntry<E> next = entry.next;
+        int newIndex = entry.hashCode & (newLength - 1);
+        entry.next = newBuckets[newIndex];
+        newBuckets[newIndex] = entry;
+        entry = next;
+      }
+    }
+    _buckets = newBuckets;
+  }
+
+  HashSet<E> _newSet() => new _HashSet<E>();
+  HashSet<R> _newSimilarSet<R>() => new _HashSet<R>();
+}
+
+class _IdentityHashSet<E> extends _HashSet<E> {
+  int _hashCode(e) => identityHashCode(e);
+  bool _equals(e1, e2) => identical(e1, e2);
+
+  HashSet<E> _newSet() => new _IdentityHashSet<E>();
+  HashSet<R> _newSimilarSet<R>() => new _IdentityHashSet<R>();
+}
+
+class _CustomHashSet<E> extends _HashSet<E> {
+  final _Equality<E> _equality;
+  final _Hasher<E> _hasher;
+  final _Predicate _validKey;
+  _CustomHashSet(this._equality, this._hasher, bool validKey(Object o))
+      : _validKey = (validKey != null) ? validKey : new _TypeTest<E>().test;
+
+  bool remove(Object element) {
+    if (!_validKey(element)) return false;
+    return super.remove(element);
+  }
+
+  bool contains(Object element) {
+    if (!_validKey(element)) return false;
+    return super.contains(element);
+  }
+
+  E lookup(Object element) {
+    if (!_validKey(element)) return null;
+    return super.lookup(element);
+  }
+
+  bool containsAll(Iterable<Object> elements) {
+    for (Object element in elements) {
+      if (!_validKey(element) || !this.contains(element)) return false;
+    }
+    return true;
+  }
+
+  void removeAll(Iterable<Object> elements) {
+    for (Object element in elements) {
+      if (_validKey(element)) {
+        super._remove(element, _hasher(element));
+      }
+    }
+  }
+
+  bool _equals(e1, e2) => _equality(e1, e2);
+  int _hashCode(e) => _hasher(e);
+
+  HashSet<E> _newSet() => new _CustomHashSet<E>(_equality, _hasher, _validKey);
+  HashSet<R> _newSimilarSet<R>() => new _HashSet<R>();
+}
+
+class _HashSetEntry<E> {
+  final E key;
+  final int hashCode;
+  _HashSetEntry<E> next;
+  _HashSetEntry(this.key, this.hashCode, this.next);
+
+  _HashSetEntry<E> remove() {
+    final result = next;
+    next = null;
+    return result;
+  }
+}
+
+class _HashSetIterator<E> implements Iterator<E> {
+  final _HashSet<E> _set;
+  final int _modificationCount;
+  int _index = 0;
+  _HashSetEntry<E> _next;
+  E _current;
+
+  _HashSetIterator(this._set) : _modificationCount = _set._modificationCount;
+
+  bool moveNext() {
+    if (_modificationCount != _set._modificationCount) {
+      throw new ConcurrentModificationError(_set);
+    }
+    if (_next != null) {
+      _current = _next.key;
+      _next = _next.next;
+      return true;
+    }
+    List<_HashSetEntry<E>> buckets = _set._buckets;
+    while (_index < buckets.length) {
+      _next = buckets[_index];
+      _index = _index + 1;
+      if (_next != null) {
+        _current = _next.key;
+        _next = _next.next;
+        return true;
+      }
+    }
+    _current = null;
+    return false;
+  }
+
+  E get current => _current;
+}
+
+/**
+ * A hash-based map that iterates keys and values in key insertion order.
+ * This is never actually instantiated any more - the constructor always
+ * returns an instance of _CompactLinkedHashMap or _InternalLinkedHashMap,
+ * which despite the names do not use links (but are insertion-ordered as if
+ * they did).
+ */
+@patch
+class LinkedHashMap<K, V> {
+  @patch
+  factory LinkedHashMap(
+      {bool equals(K key1, K key2),
+      int hashCode(K key),
+      bool isValidKey(potentialKey)}) {
+    if (isValidKey == null) {
+      if (hashCode == null) {
+        if (equals == null) {
+          return new _InternalLinkedHashMap<K, V>();
+        }
+        hashCode = _defaultHashCode;
+      } else {
+        if (identical(identityHashCode, hashCode) &&
+            identical(identical, equals)) {
+          return new _CompactLinkedIdentityHashMap<K, V>();
+        }
+        equals ??= _defaultEquals;
+      }
+    } else {
+      hashCode ??= _defaultHashCode;
+      equals ??= _defaultEquals;
+    }
+    return new _CompactLinkedCustomHashMap<K, V>(equals, hashCode, isValidKey);
+  }
+
+  @patch
+  factory LinkedHashMap.identity() => new _CompactLinkedIdentityHashMap<K, V>();
+}
+
+@patch
+class LinkedHashSet<E> {
+  @patch
+  factory LinkedHashSet(
+      {bool equals(E e1, E e2),
+      int hashCode(E e),
+      bool isValidKey(potentialKey)}) {
+    if (isValidKey == null) {
+      if (hashCode == null) {
+        if (equals == null) {
+          return new _CompactLinkedHashSet<E>();
+        }
+        hashCode = _defaultHashCode;
+      } else {
+        if (identical(identityHashCode, hashCode) &&
+            identical(identical, equals)) {
+          return new _CompactLinkedIdentityHashSet<E>();
+        }
+        equals ??= _defaultEquals;
+      }
+    } else {
+      hashCode ??= _defaultHashCode;
+      equals ??= _defaultEquals;
+    }
+    return new _CompactLinkedCustomHashSet<E>(equals, hashCode, isValidKey);
+  }
+
+  @patch
+  factory LinkedHashSet.identity() => new _CompactLinkedIdentityHashSet<E>();
+}
+
+@patch
+abstract class _SplayTree<K, Node extends _SplayTreeNode<K>> {
+  // We override _splayMin and _splayMax to optimize type-checks.
+  @patch
+  Node _splayMin(Node node) {
+    Node current = node;
+    while (current.left != null) {
+      Node left = internal.unsafeCast<Node>(current.left);
+      current.left = left.right;
+      left.right = current;
+      current = left;
+    }
+    return current;
+  }
+
+  @patch
+  Node _splayMax(Node node) {
+    Node current = node;
+    while (current.right != null) {
+      Node right = internal.unsafeCast<Node>(current.right);
+      current.right = right.left;
+      right.left = current;
+      current = right;
+    }
+    return current;
+  }
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/compact_hash.dart b/sdk_nnbd/lib/_internal/vm/lib/compact_hash.dart
new file mode 100644
index 0000000..d5a284f
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/compact_hash.dart
@@ -0,0 +1,664 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "collection_patch.dart";
+
+// Hash table with open addressing that separates the index from keys/values.
+
+// This function takes care of rehashing of the linked hashmaps in [objects]. We
+// do this eagerly after snapshot deserialization.
+@pragma("vm:entry-point", "call")
+void _rehashObjects(List objects) {
+  final int length = objects.length;
+  for (int i = 0; i < length; ++i) {
+    objects[i]._regenerateIndex();
+  }
+}
+
+abstract class _HashFieldBase {
+  // Each occupied entry in _index is a fixed-size integer that encodes a pair:
+  //   [ hash pattern for key | index of entry in _data ]
+  // The hash pattern is based on hashCode, but is guaranteed to be non-zero.
+  // The length of _index is always a power of two, and there is always at
+  // least one unoccupied entry.
+  // NOTE: When maps are deserialized, their _index and _hashMask is regenerated
+  // eagerly by _regenerateIndex.
+  Uint32List _index = new Uint32List(_HashBase._INITIAL_INDEX_SIZE);
+
+  // Cached in-place mask for the hash pattern component.
+  int _hashMask = _HashBase._indexSizeToHashMask(_HashBase._INITIAL_INDEX_SIZE);
+
+  // Fixed-length list of keys (set) or key/value at even/odd indices (map).
+  List _data;
+
+  // Length of _data that is used (i.e., keys + values for a map).
+  int _usedData = 0;
+
+  // Number of deleted keys.
+  int _deletedKeys = 0;
+
+  // Note: All fields are initialized in a single constructor so that the VM
+  // recognizes they cannot hold null values. This makes a big (20%) performance
+  // difference on some operations.
+  _HashFieldBase(int dataSize) : this._data = new List(dataSize);
+}
+
+// Base class for VM-internal classes; keep in sync with _HashFieldBase.
+abstract class _HashVMBase {
+  @pragma("vm:exact-result-type", "dart:typed_data#_Uint32List")
+  @pragma("vm:prefer-inline")
+  Uint32List get _index native "LinkedHashMap_getIndex";
+  @pragma("vm:prefer-inline")
+  void set _index(Uint32List value) native "LinkedHashMap_setIndex";
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  @pragma("vm:prefer-inline")
+  int get _hashMask native "LinkedHashMap_getHashMask";
+  @pragma("vm:prefer-inline")
+  void set _hashMask(int value) native "LinkedHashMap_setHashMask";
+
+  @pragma("vm:exact-result-type", "dart:core#_List")
+  @pragma("vm:prefer-inline")
+  List get _data native "LinkedHashMap_getData";
+  @pragma("vm:prefer-inline")
+  void set _data(List value) native "LinkedHashMap_setData";
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  @pragma("vm:prefer-inline")
+  int get _usedData native "LinkedHashMap_getUsedData";
+  @pragma("vm:prefer-inline")
+  void set _usedData(int value) native "LinkedHashMap_setUsedData";
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  @pragma("vm:prefer-inline")
+  int get _deletedKeys native "LinkedHashMap_getDeletedKeys";
+  @pragma("vm:prefer-inline")
+  void set _deletedKeys(int value) native "LinkedHashMap_setDeletedKeys";
+}
+
+// This mixin can be applied to _HashFieldBase or _HashVMBase (for
+// normal and VM-internalized classes, respectiveley), which provide the
+// actual fields/accessors that this mixin assumes.
+// TODO(koda): Consider moving field comments to _HashFieldBase.
+abstract class _HashBase implements _HashVMBase {
+  // The number of bits used for each component is determined by table size.
+  // The length of _index is twice the number of entries in _data, and both
+  // are doubled when _data is full. Thus, _index will have a max load factor
+  // of 1/2, which enables one more bit to be used for the hash.
+  // TODO(koda): Consider growing _data by factor sqrt(2), twice as often.
+  static const int _INITIAL_INDEX_BITS = 3;
+  static const int _INITIAL_INDEX_SIZE = 1 << (_INITIAL_INDEX_BITS + 1);
+
+  // Unused and deleted entries are marked by 0 and 1, respectively.
+  static const int _UNUSED_PAIR = 0;
+  static const int _DELETED_PAIR = 1;
+
+  // On 32-bit, the top bits are wasted to avoid Mint allocation.
+  // TODO(koda): Reclaim the bits by making the compiler treat hash patterns
+  // as unsigned words.
+  static int _indexSizeToHashMask(int indexSize) {
+    int indexBits = indexSize.bitLength - 2;
+    return internal.is64Bit
+        ? (1 << (32 - indexBits)) - 1
+        : (1 << (30 - indexBits)) - 1;
+  }
+
+  static int _hashPattern(int fullHash, int hashMask, int size) {
+    final int maskedHash = fullHash & hashMask;
+    // TODO(koda): Consider keeping bit length and use left shift.
+    return (maskedHash == 0) ? (size >> 1) : maskedHash * (size >> 1);
+  }
+
+  // Linear probing.
+  static int _firstProbe(int fullHash, int sizeMask) {
+    final int i = fullHash & sizeMask;
+    // Light, fast shuffle to mitigate bad hashCode (e.g., sequential).
+    return ((i << 1) + i) & sizeMask;
+  }
+
+  static int _nextProbe(int i, int sizeMask) => (i + 1) & sizeMask;
+
+  // A self-loop is used to mark a deleted key or value.
+  static bool _isDeleted(List data, Object keyOrValue) =>
+      identical(keyOrValue, data);
+  static void _setDeletedAt(List data, int d) {
+    data[d] = data;
+  }
+
+  // Concurrent modification detection relies on this checksum monotonically
+  // increasing between reallocations of _data.
+  int get _checkSum => _usedData + _deletedKeys;
+  bool _isModifiedSince(List oldData, int oldCheckSum) =>
+      !identical(_data, oldData) || (_checkSum != oldCheckSum);
+
+  int get length;
+}
+
+class _OperatorEqualsAndHashCode {
+  int _hashCode(e) => e.hashCode;
+  bool _equals(e1, e2) => e1 == e2;
+}
+
+class _IdenticalAndIdentityHashCode {
+  int _hashCode(e) => identityHashCode(e);
+  bool _equals(e1, e2) => identical(e1, e2);
+}
+
+// VM-internalized implementation of a default-constructed LinkedHashMap.
+@pragma("vm:entry-point")
+class _InternalLinkedHashMap<K, V> extends _HashVMBase
+    with
+        MapMixin<K, V>,
+        _LinkedHashMapMixin<K, V>,
+        _HashBase,
+        _OperatorEqualsAndHashCode
+    implements LinkedHashMap<K, V> {
+  _InternalLinkedHashMap() {
+    _index = new Uint32List(_HashBase._INITIAL_INDEX_SIZE);
+    _hashMask = _HashBase._indexSizeToHashMask(_HashBase._INITIAL_INDEX_SIZE);
+    _data = new List(_HashBase._INITIAL_INDEX_SIZE);
+    _usedData = 0;
+    _deletedKeys = 0;
+  }
+}
+
+abstract class _LinkedHashMapMixin<K, V> implements _HashBase {
+  int _hashCode(e);
+  bool _equals(e1, e2);
+  int get _checkSum;
+  bool _isModifiedSince(List oldData, int oldCheckSum);
+
+  int get length => (_usedData >> 1) - _deletedKeys;
+  bool get isEmpty => length == 0;
+  bool get isNotEmpty => !isEmpty;
+
+  void _rehash() {
+    if ((_deletedKeys << 2) > _usedData) {
+      // TODO(koda): Consider shrinking.
+      // TODO(koda): Consider in-place compaction and more costly CME check.
+      _init(_index.length, _hashMask, _data, _usedData);
+    } else {
+      // TODO(koda): Support 32->64 bit transition (and adjust _hashMask).
+      _init(_index.length << 1, _hashMask >> 1, _data, _usedData);
+    }
+  }
+
+  void clear() {
+    if (!isEmpty) {
+      _init(_HashBase._INITIAL_INDEX_SIZE, _hashMask, null, 0);
+    }
+  }
+
+  // Allocate new _index and _data, and optionally copy existing contents.
+  void _init(int size, int hashMask, List oldData, int oldUsed) {
+    assert(size & (size - 1) == 0);
+    assert(_HashBase._UNUSED_PAIR == 0);
+    _index = new Uint32List(size);
+    _hashMask = hashMask;
+    _data = new List(size);
+    _usedData = 0;
+    _deletedKeys = 0;
+    if (oldData != null) {
+      for (int i = 0; i < oldUsed; i += 2) {
+        var key = oldData[i];
+        if (!_HashBase._isDeleted(oldData, key)) {
+          // TODO(koda): While there are enough hash bits, avoid hashCode calls.
+          this[key] = oldData[i + 1];
+        }
+      }
+    }
+  }
+
+  // This method is called by [_rehashObjects] (see above).
+  void _regenerateIndex() {
+    _index = new Uint32List(_data.length);
+    assert(_hashMask == 0);
+    _hashMask = _HashBase._indexSizeToHashMask(_index.length);
+    final int tmpUsed = _usedData;
+    _usedData = 0;
+    for (int i = 0; i < tmpUsed; i += 2) {
+      this[_data[i]] = _data[i + 1];
+    }
+  }
+
+  void _insert(K key, V value, int hashPattern, int i) {
+    if (_usedData == _data.length) {
+      _rehash();
+      this[key] = value;
+    } else {
+      assert(1 <= hashPattern && hashPattern < (1 << 32));
+      final int index = _usedData >> 1;
+      assert((index & hashPattern) == 0);
+      _index[i] = hashPattern | index;
+      _data[_usedData++] = key;
+      _data[_usedData++] = value;
+    }
+  }
+
+  // If key is present, returns the index of the value in _data, else returns
+  // the negated insertion point in _index.
+  int _findValueOrInsertPoint(K key, int fullHash, int hashPattern, int size) {
+    final int sizeMask = size - 1;
+    final int maxEntries = size >> 1;
+    int i = _HashBase._firstProbe(fullHash, sizeMask);
+    int firstDeleted = -1;
+    int pair = _index[i];
+    while (pair != _HashBase._UNUSED_PAIR) {
+      if (pair == _HashBase._DELETED_PAIR) {
+        if (firstDeleted < 0) {
+          firstDeleted = i;
+        }
+      } else {
+        final int entry = hashPattern ^ pair;
+        if (entry < maxEntries) {
+          final int d = entry << 1;
+          if (_equals(key, _data[d])) {
+            return d + 1;
+          }
+        }
+      }
+      i = _HashBase._nextProbe(i, sizeMask);
+      pair = _index[i];
+    }
+    return firstDeleted >= 0 ? -firstDeleted : -i;
+  }
+
+  void operator []=(K key, V value) {
+    final int size = _index.length;
+    final int fullHash = _hashCode(key);
+    final int hashPattern = _HashBase._hashPattern(fullHash, _hashMask, size);
+    final int d = _findValueOrInsertPoint(key, fullHash, hashPattern, size);
+    if (d > 0) {
+      _data[d] = value;
+    } else {
+      final int i = -d;
+      _insert(key, value, hashPattern, i);
+    }
+  }
+
+  V putIfAbsent(K key, V ifAbsent()) {
+    final int size = _index.length;
+    final int fullHash = _hashCode(key);
+    final int hashPattern = _HashBase._hashPattern(fullHash, _hashMask, size);
+    final int d = _findValueOrInsertPoint(key, fullHash, hashPattern, size);
+    if (d > 0) {
+      return _data[d];
+    }
+    // 'ifAbsent' is allowed to modify the map.
+    List oldData = _data;
+    int oldCheckSum = _checkSum;
+    V value = ifAbsent();
+    if (_isModifiedSince(oldData, oldCheckSum)) {
+      this[key] = value;
+    } else {
+      final int i = -d;
+      _insert(key, value, hashPattern, i);
+    }
+    return value;
+  }
+
+  V remove(Object key) {
+    final int size = _index.length;
+    final int sizeMask = size - 1;
+    final int maxEntries = size >> 1;
+    final int fullHash = _hashCode(key);
+    final int hashPattern = _HashBase._hashPattern(fullHash, _hashMask, size);
+    int i = _HashBase._firstProbe(fullHash, sizeMask);
+    int pair = _index[i];
+    while (pair != _HashBase._UNUSED_PAIR) {
+      if (pair != _HashBase._DELETED_PAIR) {
+        final int entry = hashPattern ^ pair;
+        if (entry < maxEntries) {
+          final int d = entry << 1;
+          if (_equals(key, _data[d])) {
+            _index[i] = _HashBase._DELETED_PAIR;
+            _HashBase._setDeletedAt(_data, d);
+            V value = _data[d + 1];
+            _HashBase._setDeletedAt(_data, d + 1);
+            ++_deletedKeys;
+            return value;
+          }
+        }
+      }
+      i = _HashBase._nextProbe(i, sizeMask);
+      pair = _index[i];
+    }
+    return null;
+  }
+
+  // If key is absent, return _data (which is never a value).
+  Object _getValueOrData(Object key) {
+    final int size = _index.length;
+    final int sizeMask = size - 1;
+    final int maxEntries = size >> 1;
+    final int fullHash = _hashCode(key);
+    final int hashPattern = _HashBase._hashPattern(fullHash, _hashMask, size);
+    int i = _HashBase._firstProbe(fullHash, sizeMask);
+    int pair = _index[i];
+    while (pair != _HashBase._UNUSED_PAIR) {
+      if (pair != _HashBase._DELETED_PAIR) {
+        final int entry = hashPattern ^ pair;
+        if (entry < maxEntries) {
+          final int d = entry << 1;
+          if (_equals(key, _data[d])) {
+            return _data[d + 1];
+          }
+        }
+      }
+      i = _HashBase._nextProbe(i, sizeMask);
+      pair = _index[i];
+    }
+    return _data;
+  }
+
+  bool containsKey(Object key) => !identical(_data, _getValueOrData(key));
+
+  V operator [](Object key) {
+    var v = _getValueOrData(key);
+    return identical(_data, v) ? null : internal.unsafeCast<V>(v);
+  }
+
+  bool containsValue(Object value) {
+    for (var v in values) {
+      // Spec. says this should always use "==", also for identity maps, etc.
+      if (v == value) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  void forEach(void f(K key, V value)) {
+    var ki = keys.iterator;
+    var vi = values.iterator;
+    while (ki.moveNext()) {
+      vi.moveNext();
+      f(ki.current, vi.current);
+    }
+  }
+
+  Iterable<K> get keys =>
+      new _CompactIterable<K>(this, _data, _usedData, -2, 2);
+  Iterable<V> get values =>
+      new _CompactIterable<V>(this, _data, _usedData, -1, 2);
+}
+
+class _CompactLinkedIdentityHashMap<K, V> extends _HashFieldBase
+    with
+        MapMixin<K, V>,
+        _LinkedHashMapMixin<K, V>,
+        _HashBase,
+        _IdenticalAndIdentityHashCode
+    implements LinkedHashMap<K, V> {
+  _CompactLinkedIdentityHashMap() : super(_HashBase._INITIAL_INDEX_SIZE);
+}
+
+class _CompactLinkedCustomHashMap<K, V> extends _HashFieldBase
+    with MapMixin<K, V>, _LinkedHashMapMixin<K, V>, _HashBase
+    implements LinkedHashMap<K, V> {
+  final _equality;
+  final _hasher;
+  final _validKey;
+
+  // TODO(koda): Ask gbracha why I cannot have fields _equals/_hashCode.
+  int _hashCode(e) => _hasher(e);
+  bool _equals(e1, e2) => _equality(e1, e2);
+
+  bool containsKey(Object o) => _validKey(o) ? super.containsKey(o) : false;
+  V operator [](Object o) => _validKey(o) ? super[o] : null;
+  V remove(Object o) => _validKey(o) ? super.remove(o) : null;
+
+  _CompactLinkedCustomHashMap(this._equality, this._hasher, validKey)
+      : _validKey = (validKey != null) ? validKey : new _TypeTest<K>().test,
+        super(_HashBase._INITIAL_INDEX_SIZE);
+}
+
+// Iterates through _data[_offset + _step], _data[_offset + 2*_step], ...
+// and checks for concurrent modification.
+class _CompactIterable<E> extends Iterable<E> {
+  final _HashBase _table;
+  final List _data;
+  final int _len;
+  final int _offset;
+  final int _step;
+
+  _CompactIterable(
+      this._table, this._data, this._len, this._offset, this._step);
+
+  Iterator<E> get iterator =>
+      new _CompactIterator<E>(_table, _data, _len, _offset, _step);
+
+  int get length => _table.length;
+  bool get isEmpty => length == 0;
+  bool get isNotEmpty => !isEmpty;
+}
+
+class _CompactIterator<E> implements Iterator<E> {
+  final _HashBase _table;
+  final List _data;
+  final int _len;
+  int _offset;
+  final int _step;
+  final int _checkSum;
+  E current;
+
+  _CompactIterator(
+      _HashBase table, this._data, this._len, this._offset, this._step)
+      : _table = table,
+        _checkSum = table._checkSum;
+
+  bool moveNext() {
+    if (_table._isModifiedSince(_data, _checkSum)) {
+      throw new ConcurrentModificationError(_table);
+    }
+    do {
+      _offset += _step;
+    } while (_offset < _len && _HashBase._isDeleted(_data, _data[_offset]));
+    if (_offset < _len) {
+      current = internal.unsafeCast<E>(_data[_offset]);
+      return true;
+    } else {
+      current = null;
+      return false;
+    }
+  }
+}
+
+// Set implementation, analogous to _CompactLinkedHashMap.
+class _CompactLinkedHashSet<E> extends _HashFieldBase
+    with _HashBase, _OperatorEqualsAndHashCode, SetMixin<E>
+    implements LinkedHashSet<E> {
+  _CompactLinkedHashSet() : super(_HashBase._INITIAL_INDEX_SIZE >> 1) {
+    assert(_HashBase._UNUSED_PAIR == 0);
+  }
+
+  static Set<R> _newEmpty<R>() => new _CompactLinkedHashSet<R>();
+
+  Set<R> cast<R>() => Set.castFrom<E, R>(this, newSet: _newEmpty);
+  int get length => _usedData - _deletedKeys;
+
+  E get first {
+    for (int offset = 0; offset < _usedData; offset++) {
+      Object current = _data[offset];
+      if (!_HashBase._isDeleted(_data, current)) {
+        return current;
+      }
+    }
+    throw IterableElementError.noElement();
+  }
+
+  E get last {
+    for (int offset = _usedData - 1; offset >= 0; offset--) {
+      Object current = _data[offset];
+      if (!_HashBase._isDeleted(_data, current)) {
+        return current;
+      }
+    }
+    throw IterableElementError.noElement();
+  }
+
+  void _rehash() {
+    if ((_deletedKeys << 1) > _usedData) {
+      _init(_index.length, _hashMask, _data, _usedData);
+    } else {
+      _init(_index.length << 1, _hashMask >> 1, _data, _usedData);
+    }
+  }
+
+  void clear() {
+    if (!isEmpty) {
+      _init(_HashBase._INITIAL_INDEX_SIZE, _hashMask, null, 0);
+    }
+  }
+
+  void _init(int size, int hashMask, List oldData, int oldUsed) {
+    _index = new Uint32List(size);
+    _hashMask = hashMask;
+    _data = new List(size >> 1);
+    _usedData = 0;
+    _deletedKeys = 0;
+    if (oldData != null) {
+      for (int i = 0; i < oldUsed; i += 1) {
+        var key = oldData[i];
+        if (!_HashBase._isDeleted(oldData, key)) {
+          add(key);
+        }
+      }
+    }
+  }
+
+  bool add(E key) {
+    final int size = _index.length;
+    final int sizeMask = size - 1;
+    final int maxEntries = size >> 1;
+    final int fullHash = _hashCode(key);
+    final int hashPattern = _HashBase._hashPattern(fullHash, _hashMask, size);
+    int i = _HashBase._firstProbe(fullHash, sizeMask);
+    int firstDeleted = -1;
+    int pair = _index[i];
+    while (pair != _HashBase._UNUSED_PAIR) {
+      if (pair == _HashBase._DELETED_PAIR) {
+        if (firstDeleted < 0) {
+          firstDeleted = i;
+        }
+      } else {
+        final int d = hashPattern ^ pair;
+        if (d < maxEntries && _equals(key, _data[d])) {
+          return false;
+        }
+      }
+      i = _HashBase._nextProbe(i, sizeMask);
+      pair = _index[i];
+    }
+    if (_usedData == _data.length) {
+      _rehash();
+      add(key);
+    } else {
+      final int insertionPoint = (firstDeleted >= 0) ? firstDeleted : i;
+      assert(1 <= hashPattern && hashPattern < (1 << 32));
+      assert((hashPattern & _usedData) == 0);
+      _index[insertionPoint] = hashPattern | _usedData;
+      _data[_usedData++] = key;
+    }
+    return true;
+  }
+
+  // If key is absent, return _data (which is never a value).
+  Object _getKeyOrData(Object key) {
+    final int size = _index.length;
+    final int sizeMask = size - 1;
+    final int maxEntries = size >> 1;
+    final int fullHash = _hashCode(key);
+    final int hashPattern = _HashBase._hashPattern(fullHash, _hashMask, size);
+    int i = _HashBase._firstProbe(fullHash, sizeMask);
+    int pair = _index[i];
+    while (pair != _HashBase._UNUSED_PAIR) {
+      if (pair != _HashBase._DELETED_PAIR) {
+        final int d = hashPattern ^ pair;
+        if (d < maxEntries && _equals(key, _data[d])) {
+          return _data[d]; // Note: Must return the existing key.
+        }
+      }
+      i = _HashBase._nextProbe(i, sizeMask);
+      pair = _index[i];
+    }
+    return _data;
+  }
+
+  E lookup(Object key) {
+    var k = _getKeyOrData(key);
+    return identical(_data, k) ? null : k;
+  }
+
+  bool contains(Object key) => !identical(_data, _getKeyOrData(key));
+
+  bool remove(Object key) {
+    final int size = _index.length;
+    final int sizeMask = size - 1;
+    final int maxEntries = size >> 1;
+    final int fullHash = _hashCode(key);
+    final int hashPattern = _HashBase._hashPattern(fullHash, _hashMask, size);
+    int i = _HashBase._firstProbe(fullHash, sizeMask);
+    int pair = _index[i];
+    while (pair != _HashBase._UNUSED_PAIR) {
+      if (pair != _HashBase._DELETED_PAIR) {
+        final int d = hashPattern ^ pair;
+        if (d < maxEntries && _equals(key, _data[d])) {
+          _index[i] = _HashBase._DELETED_PAIR;
+          _HashBase._setDeletedAt(_data, d);
+          ++_deletedKeys;
+          return true;
+        }
+      }
+      i = _HashBase._nextProbe(i, sizeMask);
+      pair = _index[i];
+    }
+    return false;
+  }
+
+  Iterator<E> get iterator =>
+      new _CompactIterator<E>(this, _data, _usedData, -1, 1);
+
+  // Returns a set of the same type, although this
+  // is not required by the spec. (For instance, always using an identity set
+  // would be technically correct, albeit surprising.)
+  Set<E> toSet() => new _CompactLinkedHashSet<E>()..addAll(this);
+
+  // This method is called by [_rehashObjects] (see above).
+  void _regenerateIndex() {
+    _rehash();
+  }
+}
+
+class _CompactLinkedIdentityHashSet<E> extends _CompactLinkedHashSet<E>
+    with _IdenticalAndIdentityHashCode {
+  Set<E> toSet() => new _CompactLinkedIdentityHashSet<E>()..addAll(this);
+
+  static Set<R> _newEmpty<R>() => new _CompactLinkedIdentityHashSet<R>();
+
+  Set<R> cast<R>() => Set.castFrom<E, R>(this, newSet: _newEmpty);
+}
+
+class _CompactLinkedCustomHashSet<E> extends _CompactLinkedHashSet<E> {
+  final _equality;
+  final _hasher;
+  final _validKey;
+
+  int _hashCode(e) => _hasher(e);
+  bool _equals(e1, e2) => _equality(e1, e2);
+
+  bool contains(Object o) => _validKey(o) ? super.contains(o) : false;
+  E lookup(Object o) => _validKey(o) ? super.lookup(o) : null;
+  bool remove(Object o) => _validKey(o) ? super.remove(o) : false;
+
+  _CompactLinkedCustomHashSet(this._equality, this._hasher, validKey)
+      : _validKey = (validKey != null) ? validKey : new _TypeTest<E>().test;
+
+  Set<R> cast<R>() => Set.castFrom<E, R>(this);
+  Set<E> toSet() =>
+      new _CompactLinkedCustomHashSet<E>(_equality, _hasher, _validKey)
+        ..addAll(this);
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/convert_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/convert_patch.dart
new file mode 100644
index 0000000..4eeb85f
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/convert_patch.dart
@@ -0,0 +1,1878 @@
+// 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.
+
+// @dart = 2.5
+
+/// Note: the VM concatenates all patch files into a single patch file. This
+/// file is the first patch in "dart:convert" which contains all the imports
+/// used by patches of that library. We plan to change this when we have a
+/// shared front end and simply use parts.
+
+import "dart:_internal" show POWERS_OF_TEN, patch, ClassID;
+
+import "dart:typed_data" show Uint8List, Uint16List;
+
+/// This patch library has no additional parts.
+
+// JSON conversion.
+
+@patch
+_parseJson(String source, reviver(key, value)) {
+  _BuildJsonListener listener;
+  if (reviver == null) {
+    listener = new _BuildJsonListener();
+  } else {
+    listener = new _ReviverJsonListener(reviver);
+  }
+  var parser = new _JsonStringParser(listener);
+  parser.chunk = source;
+  parser.chunkEnd = source.length;
+  parser.parse(0);
+  parser.close();
+  return listener.result;
+}
+
+@patch
+class Utf8Decoder {
+  @patch
+  Converter<List<int>, T> fuse<T>(Converter<String, T> next) {
+    if (next is JsonDecoder) {
+      return new _JsonUtf8Decoder(
+              (next as JsonDecoder)._reviver, this._allowMalformed)
+          as dynamic/*=Converter<List<int>, T>*/;
+    }
+    // TODO(lrn): Recognize a fused decoder where the next step is JsonDecoder.
+    return super.fuse<T>(next);
+  }
+
+  // Allow intercepting of UTF-8 decoding when built-in lists are passed.
+  @patch
+  static String _convertIntercepted(
+      bool allowMalformed, List<int> codeUnits, int start, int end) {
+    return null; // This call was not intercepted.
+  }
+}
+
+class _JsonUtf8Decoder extends Converter<List<int>, Object> {
+  final Function(Object key, Object value) _reviver;
+  final bool _allowMalformed;
+
+  _JsonUtf8Decoder(this._reviver, this._allowMalformed);
+
+  Object convert(List<int> input) {
+    var parser = _JsonUtf8DecoderSink._createParser(_reviver, _allowMalformed);
+    parser.chunk = input;
+    parser.chunkEnd = input.length;
+    parser.parse(0);
+    parser.close();
+    return parser.result;
+  }
+
+  ByteConversionSink startChunkedConversion(Sink<Object> sink) {
+    return new _JsonUtf8DecoderSink(_reviver, sink, _allowMalformed);
+  }
+}
+
+//// Implementation ///////////////////////////////////////////////////////////
+
+// Simple API for JSON parsing.
+
+/**
+ * Listener for parsing events from [_ChunkedJsonParser].
+ */
+abstract class _JsonListener {
+  void handleString(String value) {}
+  void handleNumber(num value) {}
+  void handleBool(bool value) {}
+  void handleNull() {}
+  void beginObject() {}
+  void propertyName() {}
+  void propertyValue() {}
+  void endObject() {}
+  void beginArray() {}
+  void arrayElement() {}
+  void endArray() {}
+
+  /**
+   * Read out the final result of parsing a JSON string.
+   *
+   * Must only be called when the entire input has been parsed.
+   */
+  get result;
+}
+
+/**
+ * A [_JsonListener] that builds data objects from the parser events.
+ *
+ * This is a simple stack-based object builder. It keeps the most recently
+ * seen value in a variable, and uses it depending on the following event.
+ */
+class _BuildJsonListener extends _JsonListener {
+  /**
+   * Stack used to handle nested containers.
+   *
+   * The current container is pushed on the stack when a new one is
+   * started. If the container is a [Map], there is also a current [key]
+   * which is also stored on the stack.
+   */
+  List stack = [];
+  /** The current [Map] or [List] being built. */
+  var currentContainer;
+  /** The most recently read property key. */
+  String key;
+  /** The most recently read value. */
+  var value;
+
+  /** Pushes the currently active container (and key, if a [Map]). */
+  void pushContainer() {
+    if (currentContainer is Map) stack.add(key);
+    stack.add(currentContainer);
+  }
+
+  /** Pops the top container from the [stack], including a key if applicable. */
+  void popContainer() {
+    value = currentContainer;
+    currentContainer = stack.removeLast();
+    if (currentContainer is Map) key = stack.removeLast();
+  }
+
+  void handleString(String value) {
+    this.value = value;
+  }
+
+  void handleNumber(num value) {
+    this.value = value;
+  }
+
+  void handleBool(bool value) {
+    this.value = value;
+  }
+
+  void handleNull() {
+    this.value = null;
+  }
+
+  void beginObject() {
+    pushContainer();
+    currentContainer = <String, dynamic>{};
+  }
+
+  void propertyName() {
+    key = value;
+    value = null;
+  }
+
+  void propertyValue() {
+    Map map = currentContainer;
+    map[key] = value;
+    key = value = null;
+  }
+
+  void endObject() {
+    popContainer();
+  }
+
+  void beginArray() {
+    pushContainer();
+    currentContainer = [];
+  }
+
+  void arrayElement() {
+    currentContainer.add(value);
+    value = null;
+  }
+
+  void endArray() {
+    popContainer();
+  }
+
+  /** Read out the final result of parsing a JSON string. */
+  get result {
+    assert(currentContainer == null);
+    return value;
+  }
+}
+
+class _ReviverJsonListener extends _BuildJsonListener {
+  final Function(Object key, Object value) reviver;
+  _ReviverJsonListener(this.reviver);
+
+  void arrayElement() {
+    List list = currentContainer;
+    value = reviver(list.length, value);
+    super.arrayElement();
+  }
+
+  void propertyValue() {
+    value = reviver(key, value);
+    super.propertyValue();
+  }
+
+  get result {
+    return reviver(null, value);
+  }
+}
+
+/**
+ * Buffer holding parts of a numeral.
+ *
+ * The buffer contains the characters of a JSON number.
+ * These are all ASCII, so an [Uint8List] is used as backing store.
+ *
+ * This buffer is used when a JSON number is split between separate chunks.
+ *
+ */
+class _NumberBuffer {
+  static const int minCapacity = 16;
+  static const int kDefaultOverhead = 5;
+  Uint8List list;
+  int length = 0;
+  _NumberBuffer(int initialCapacity)
+      : list = new Uint8List(_initialCapacity(initialCapacity));
+
+  int get capacity => list.length;
+
+  // Pick an initial capacity greater than the first part's size.
+  // The typical use case has two parts, this is the attempt at
+  // guessing the size of the second part without overdoing it.
+  // The default estimate of the second part is [kDefaultOverhead],
+  // then round to multiplum of four, and return the result,
+  // or [minCapacity] if that is greater.
+  static int _initialCapacity(int minCapacity) {
+    minCapacity += kDefaultOverhead;
+    if (minCapacity < minCapacity) return minCapacity;
+    minCapacity = (minCapacity + 3) & ~3; // Round to multiple of four.
+    return minCapacity;
+  }
+
+  // Grows to the exact size asked for.
+  void ensureCapacity(int newCapacity) {
+    Uint8List list = this.list;
+    if (newCapacity <= list.length) return;
+    Uint8List newList = new Uint8List(newCapacity);
+    newList.setRange(0, list.length, list, 0);
+    this.list = newList;
+  }
+
+  String getString() {
+    String result = new String.fromCharCodes(list, 0, length);
+    return result;
+  }
+
+  // TODO(lrn): See if parsing of numbers can be abstracted to something
+  // not only working on strings, but also on char-code lists, without lossing
+  // performance.
+  num parseNum() => num.parse(getString());
+  double parseDouble() => double.parse(getString());
+}
+
+/**
+ * Chunked JSON parser.
+ *
+ * Receives inputs in chunks, gives access to individual parts of the input,
+ * and stores input state between chunks.
+ *
+ * Implementations include [String] and UTF-8 parsers.
+ */
+abstract class _ChunkedJsonParser<T> {
+  // A simple non-recursive state-based parser for JSON.
+  //
+  // Literal values accepted in states ARRAY_EMPTY, ARRAY_COMMA, OBJECT_COLON
+  // and strings also in OBJECT_EMPTY, OBJECT_COMMA.
+  //               VALUE  STRING  :  ,  }  ]        Transitions to
+  // EMPTY            X      X                   -> END
+  // ARRAY_EMPTY      X      X             @     -> ARRAY_VALUE / pop
+  // ARRAY_VALUE                     @     @     -> ARRAY_COMMA / pop
+  // ARRAY_COMMA      X      X                   -> ARRAY_VALUE
+  // OBJECT_EMPTY            X          @        -> OBJECT_KEY / pop
+  // OBJECT_KEY                   @              -> OBJECT_COLON
+  // OBJECT_COLON     X      X                   -> OBJECT_VALUE
+  // OBJECT_VALUE                    @  @        -> OBJECT_COMMA / pop
+  // OBJECT_COMMA            X                   -> OBJECT_KEY
+  // END
+  // Starting a new array or object will push the current state. The "pop"
+  // above means restoring this state and then marking it as an ended value.
+  // X means generic handling, @ means special handling for just that
+  // state - that is, values are handled generically, only punctuation
+  // cares about the current state.
+  // Values for states are chosen so bits 0 and 1 tell whether
+  // a string/value is allowed, and setting bits 0 through 2 after a value
+  // gets to the next state (not empty, doesn't allow a value).
+
+  // State building-block constants.
+  static const int TOP_LEVEL = 0;
+  static const int INSIDE_ARRAY = 1;
+  static const int INSIDE_OBJECT = 2;
+  static const int AFTER_COLON = 3; // Always inside object.
+
+  static const int ALLOW_STRING_MASK = 8; // Allowed if zero.
+  static const int ALLOW_VALUE_MASK = 4; // Allowed if zero.
+  static const int ALLOW_VALUE = 0;
+  static const int STRING_ONLY = 4;
+  static const int NO_VALUES = 12;
+
+  // Objects and arrays are "empty" until their first property/element.
+  // At this position, they may either have an entry or a close-bracket.
+  static const int EMPTY = 0;
+  static const int NON_EMPTY = 16;
+  static const int EMPTY_MASK = 16; // Empty if zero.
+
+  // Actual states               : Context | Is empty? | Next?
+  static const int STATE_INITIAL = TOP_LEVEL | EMPTY | ALLOW_VALUE;
+  static const int STATE_END = TOP_LEVEL | NON_EMPTY | NO_VALUES;
+
+  static const int STATE_ARRAY_EMPTY = INSIDE_ARRAY | EMPTY | ALLOW_VALUE;
+  static const int STATE_ARRAY_VALUE = INSIDE_ARRAY | NON_EMPTY | NO_VALUES;
+  static const int STATE_ARRAY_COMMA = INSIDE_ARRAY | NON_EMPTY | ALLOW_VALUE;
+
+  static const int STATE_OBJECT_EMPTY = INSIDE_OBJECT | EMPTY | STRING_ONLY;
+  static const int STATE_OBJECT_KEY = INSIDE_OBJECT | NON_EMPTY | NO_VALUES;
+  static const int STATE_OBJECT_COLON = AFTER_COLON | NON_EMPTY | ALLOW_VALUE;
+  static const int STATE_OBJECT_VALUE = AFTER_COLON | NON_EMPTY | NO_VALUES;
+  static const int STATE_OBJECT_COMMA = INSIDE_OBJECT | NON_EMPTY | STRING_ONLY;
+
+  // Bits set in state after successfully reading a value.
+  // This transitions the state to expect the next punctuation.
+  static const int VALUE_READ_BITS = NON_EMPTY | NO_VALUES;
+
+  // Character code constants.
+  static const int BACKSPACE = 0x08;
+  static const int TAB = 0x09;
+  static const int NEWLINE = 0x0a;
+  static const int CARRIAGE_RETURN = 0x0d;
+  static const int FORM_FEED = 0x0c;
+  static const int SPACE = 0x20;
+  static const int QUOTE = 0x22;
+  static const int PLUS = 0x2b;
+  static const int COMMA = 0x2c;
+  static const int MINUS = 0x2d;
+  static const int DECIMALPOINT = 0x2e;
+  static const int SLASH = 0x2f;
+  static const int CHAR_0 = 0x30;
+  static const int CHAR_9 = 0x39;
+  static const int COLON = 0x3a;
+  static const int CHAR_E = 0x45;
+  static const int LBRACKET = 0x5b;
+  static const int BACKSLASH = 0x5c;
+  static const int RBRACKET = 0x5d;
+  static const int CHAR_a = 0x61;
+  static const int CHAR_b = 0x62;
+  static const int CHAR_e = 0x65;
+  static const int CHAR_f = 0x66;
+  static const int CHAR_l = 0x6c;
+  static const int CHAR_n = 0x6e;
+  static const int CHAR_r = 0x72;
+  static const int CHAR_s = 0x73;
+  static const int CHAR_t = 0x74;
+  static const int CHAR_u = 0x75;
+  static const int LBRACE = 0x7b;
+  static const int RBRACE = 0x7d;
+
+  // State of partial value at chunk split.
+  static const int NO_PARTIAL = 0;
+  static const int PARTIAL_STRING = 1;
+  static const int PARTIAL_NUMERAL = 2;
+  static const int PARTIAL_KEYWORD = 3;
+  static const int MASK_PARTIAL = 3;
+
+  // Partial states for numerals. Values can be |'ed with PARTIAL_NUMERAL.
+  static const int NUM_SIGN = 0; // After initial '-'.
+  static const int NUM_ZERO = 4; // After '0' as first digit.
+  static const int NUM_DIGIT = 8; // After digit, no '.' or 'e' seen.
+  static const int NUM_DOT = 12; // After '.'.
+  static const int NUM_DOT_DIGIT = 16; // After a decimal digit (after '.').
+  static const int NUM_E = 20; // After 'e' or 'E'.
+  static const int NUM_E_SIGN = 24; // After '-' or '+' after 'e' or 'E'.
+  static const int NUM_E_DIGIT = 28; // After exponent digit.
+  static const int NUM_SUCCESS = 32; // Never stored as partial state.
+
+  // Partial states for strings.
+  static const int STR_PLAIN = 0; // Inside string, but not escape.
+  static const int STR_ESCAPE = 4; // After '\'.
+  static const int STR_U = 16; // After '\u' and 0-3 hex digits.
+  static const int STR_U_COUNT_SHIFT = 2; // Hex digit count in bits 2-3.
+  static const int STR_U_VALUE_SHIFT = 5; // Hex digit value in bits 5+.
+
+  // Partial states for keywords.
+  static const int KWD_TYPE_MASK = 12;
+  static const int KWD_TYPE_SHIFT = 2;
+  static const int KWD_NULL = 0; // Prefix of "null" seen.
+  static const int KWD_TRUE = 4; // Prefix of "true" seen.
+  static const int KWD_FALSE = 8; // Prefix of "false" seen.
+  static const int KWD_BOM = 12; // Prefix of BOM seen.
+  static const int KWD_COUNT_SHIFT = 4; // Prefix length in bits 4+.
+
+  // Mask used to mask off two lower bits.
+  static const int TWO_BIT_MASK = 3;
+
+  final _JsonListener listener;
+
+  // The current parsing state.
+  int state = STATE_INITIAL;
+  List<int> states = <int>[];
+
+  /**
+   * Stores tokenizer state between chunks.
+   *
+   * This state is stored when a chunk stops in the middle of a
+   * token (string, numeral, boolean or null).
+   *
+   * The partial state is used to continue parsing on the next chunk.
+   * The previous chunk is not retained, any data needed are stored in
+   * this integer, or in the [buffer] field as a string-building buffer
+   * or a [_NumberBuffer].
+   *
+   * Prefix state stored in [prefixState] as bits.
+   *
+   *            ..00 : No partial value (NO_PARTIAL).
+   *
+   *         ..00001 : Partial string, not inside escape.
+   *         ..00101 : Partial string, after '\'.
+   *     ..vvvv1dd01 : Partial \u escape.
+   *                   The 'dd' bits (2-3) encode the number of hex digits seen.
+   *                   Bits 5-16 encode the value of the hex digits seen so far.
+   *
+   *        ..0ddd10 : Partial numeral.
+   *                   The `ddd` bits store the parts of in the numeral seen so
+   *                   far, as the constants `NUM_*` defined above.
+   *                   The characters of the numeral are stored in [buffer]
+   *                   as a [_NumberBuffer].
+   *
+   *      ..0ddd0011 : Partial 'null' keyword.
+   *      ..0ddd0111 : Partial 'true' keyword.
+   *      ..0ddd1011 : Partial 'false' keyword.
+   *      ..0ddd1111 : Partial UTF-8 BOM byte seqeuence ("\xEF\xBB\xBF").
+   *                   For all keywords, the `ddd` bits encode the number
+   *                   of letters seen.
+   *                   The BOM byte sequence is only used by [_JsonUtf8Parser],
+   *                   and only at the very beginning of input.
+   */
+  int partialState = NO_PARTIAL;
+
+  /**
+   * Extra data stored while parsing a primitive value.
+   * May be set during parsing, always set at chunk end if a value is partial.
+   *
+   * May contain a string buffer while parsing strings.
+   */
+  var buffer = null;
+
+  _ChunkedJsonParser(this.listener);
+
+  /**
+   * Push the current parse [state] on a stack.
+   *
+   * State is pushed when a new array or object literal starts,
+   * so the parser can go back to the correct value when the literal ends.
+   */
+  void saveState(int state) {
+    states.add(state);
+  }
+
+  /**
+   * Restore a state pushed with [saveState].
+   */
+  int restoreState() {
+    return states.removeLast(); // Throws if empty.
+  }
+
+  /**
+   * Finalizes the parsing.
+   *
+   * Throws if the source read so far doesn't end up with a complete
+   * parsed value. That means it must not be inside a list or object
+   * literal, and any partial value read should also be a valid complete
+   * value.
+   *
+   * The only valid partial state is a number that ends in a digit, and
+   * only if the number is the entire JSON value being parsed
+   * (otherwise it would be inside a list or object).
+   * Such a number will be completed. Any other partial state is an error.
+   */
+  void close() {
+    if (partialState != NO_PARTIAL) {
+      int partialType = partialState & MASK_PARTIAL;
+      if (partialType == PARTIAL_NUMERAL) {
+        int numState = partialState & ~MASK_PARTIAL;
+        // A partial number might be a valid number if we know it's done.
+        // There is an unnecessary overhead if input is a single number,
+        // but this is assumed to be rare.
+        _NumberBuffer buffer = this.buffer;
+        this.buffer = null;
+        finishChunkNumber(numState, 0, 0, buffer);
+      } else if (partialType == PARTIAL_STRING) {
+        fail(chunkEnd, "Unterminated string");
+      } else {
+        assert(partialType == PARTIAL_KEYWORD);
+        fail(chunkEnd); // Incomplete literal.
+      }
+    }
+    if (state != STATE_END) {
+      fail(chunkEnd);
+    }
+  }
+
+  /**
+   * Read out the result after successfully closing the parser.
+   *
+   * The parser is closed by calling [close] or calling [addSourceChunk] with
+   * `true` as second (`isLast`) argument.
+   */
+  Object get result {
+    return listener.result;
+  }
+
+  /** Sets the current source chunk. */
+  void set chunk(T source);
+
+  /**
+   * Length of current chunk.
+   *
+   * The valid arguments to [getChar] are 0 .. `chunkEnd - 1`.
+   */
+  int get chunkEnd;
+
+  /**
+   * Returns the chunk itself.
+   *
+   * Only used by [fail] to include the chunk in the thrown [FormatException].
+   */
+  T get chunk;
+
+  /**
+   * Get charcacter/code unit of current chunk.
+   *
+   * The [index] must be non-negative and less than `chunkEnd`.
+   * In practive, [index] will be no smaller than the `start` argument passed
+   * to [parse].
+   */
+  int getChar(int index);
+
+  /**
+   * Copy ASCII characters from start to end of chunk into a list.
+   *
+   * Used for number buffer (always copies ASCII, so encoding is not important).
+   */
+  void copyCharsToList(int start, int end, List<int> target, int offset);
+
+  /**
+   * Build a string using input code units.
+   *
+   * Creates a string buffer and enables adding characters and slices
+   * to that buffer.
+   * The buffer is stored in the [buffer] field. If the string is unterminated,
+   * the same buffer is used to continue parsing in the next chunk.
+   */
+  void beginString();
+  /**
+   * Add single character code to string being built.
+   *
+   * Used for unparsed escape sequences.
+   */
+  void addCharToString(int charCode);
+
+  /**
+   * Adds slice of current chunk to string being built.
+   *
+   * The [start] positions is inclusive, [end] is exclusive.
+   */
+  void addSliceToString(int start, int end);
+
+  /** Finalizes the string being built and returns it as a String. */
+  String endString();
+
+  /**
+   * Extracts a literal string from a slice of the current chunk.
+   *
+   * No interpretation of the content is performed, except for converting
+   * the source format to string.
+   * This can be implemented more or less efficiently depending on the
+   * underlying source.
+   *
+   * This is used for string literals that contain no escapes.
+   *
+   * The [bits] integer is an upper bound on the code point in the range
+   * from `start` to `end`.
+   * Usually found by doing bitwise or of all the values.
+   * The function may choose to optimize depending on the value.
+   */
+  String getString(int start, int end, int bits);
+
+  /**
+   * Parse a slice of the current chunk as a number.
+   *
+   * Since integers have a maximal value, and we don't track the value
+   * in the buffer, a sequence of digits can be either an int or a double.
+   * The `num.parse` function does the right thing.
+   *
+   * The format is expected to be correct.
+   */
+  num parseNum(int start, int end) {
+    const int asciiBits = 0x7f; // Number literals are ASCII only.
+    return num.parse(getString(start, end, asciiBits));
+  }
+
+  /**
+   * Parse a slice of the current chunk as a double.
+   *
+   * The format is expected to be correct.
+   * This is used by [parseNumber] when the double value cannot be
+   * built exactly during parsing.
+   */
+  double parseDouble(int start, int end) {
+    const int asciiBits = 0x7f; // Double literals are ASCII only.
+    return double.parse(getString(start, end, asciiBits));
+  }
+
+  /**
+   * Continues parsing a partial value.
+   */
+  int parsePartial(int position) {
+    if (position == chunkEnd) return position;
+    int partialState = this.partialState;
+    assert(partialState != NO_PARTIAL);
+    int partialType = partialState & MASK_PARTIAL;
+    this.partialState = NO_PARTIAL;
+    partialState = partialState & ~MASK_PARTIAL;
+    assert(partialType != 0);
+    if (partialType == PARTIAL_STRING) {
+      position = parsePartialString(position, partialState);
+    } else if (partialType == PARTIAL_NUMERAL) {
+      position = parsePartialNumber(position, partialState);
+    } else if (partialType == PARTIAL_KEYWORD) {
+      position = parsePartialKeyword(position, partialState);
+    }
+    return position;
+  }
+
+  /**
+   * Parses the remainder of a number into the number buffer.
+   *
+   * Syntax is checked while pasing.
+   * Starts at position, which is expected to be the start of the chunk,
+   * and returns the index of the first non-number-literal character found,
+   * or chunkEnd if the entire chunk is a valid number continuation.
+   * Throws if a syntax error is detected.
+   */
+  int parsePartialNumber(int position, int state) {
+    int start = position;
+    // Primitive implementation, can be optimized.
+    _NumberBuffer buffer = this.buffer;
+    this.buffer = null;
+    int end = chunkEnd;
+    toBailout:
+    {
+      if (position == end) break toBailout;
+      int char = getChar(position);
+      int digit = char ^ CHAR_0;
+      if (state == NUM_SIGN) {
+        if (digit <= 9) {
+          if (digit == 0) {
+            state = NUM_ZERO;
+          } else {
+            state = NUM_DIGIT;
+          }
+          position++;
+          if (position == end) break toBailout;
+          char = getChar(position);
+          digit = char ^ CHAR_0;
+        } else {
+          return fail(position);
+        }
+      }
+      if (state == NUM_ZERO) {
+        // JSON does not allow insignificant leading zeros (e.g., "09").
+        if (digit <= 9) return fail(position);
+        state = NUM_DIGIT;
+      }
+      while (state == NUM_DIGIT) {
+        if (digit > 9) {
+          if (char == DECIMALPOINT) {
+            state = NUM_DOT;
+          } else if ((char | 0x20) == CHAR_e) {
+            state = NUM_E;
+          } else {
+            finishChunkNumber(state, start, position, buffer);
+            return position;
+          }
+        }
+        position++;
+        if (position == end) break toBailout;
+        char = getChar(position);
+        digit = char ^ CHAR_0;
+      }
+      if (state == NUM_DOT) {
+        if (digit > 9) return fail(position);
+        state = NUM_DOT_DIGIT;
+      }
+      while (state == NUM_DOT_DIGIT) {
+        if (digit > 9) {
+          if ((char | 0x20) == CHAR_e) {
+            state = NUM_E;
+          } else {
+            finishChunkNumber(state, start, position, buffer);
+            return position;
+          }
+        }
+        position++;
+        if (position == end) break toBailout;
+        char = getChar(position);
+        digit = char ^ CHAR_0;
+      }
+      if (state == NUM_E) {
+        if (char == PLUS || char == MINUS) {
+          state = NUM_E_SIGN;
+          position++;
+          if (position == end) break toBailout;
+          char = getChar(position);
+          digit = char ^ CHAR_0;
+        }
+      }
+      assert(state >= NUM_E);
+      while (digit <= 9) {
+        state = NUM_E_DIGIT;
+        position++;
+        if (position == end) break toBailout;
+        char = getChar(position);
+        digit = char ^ CHAR_0;
+      }
+      finishChunkNumber(state, start, position, buffer);
+      return position;
+    }
+    // Bailout code in case the current chunk ends while parsing the numeral.
+    assert(position == end);
+    continueChunkNumber(state, start, buffer);
+    return chunkEnd;
+  }
+
+  /**
+   * Continues parsing a partial string literal.
+   *
+   * Handles partial escapes and then hands the parsing off to
+   * [parseStringToBuffer].
+   */
+  int parsePartialString(int position, int partialState) {
+    if (partialState == STR_PLAIN) {
+      return parseStringToBuffer(position);
+    }
+    if (partialState == STR_ESCAPE) {
+      position = parseStringEscape(position);
+      // parseStringEscape sets partialState if it sees the end.
+      if (position == chunkEnd) return position;
+      return parseStringToBuffer(position);
+    }
+    assert((partialState & STR_U) != 0);
+    int value = partialState >> STR_U_VALUE_SHIFT;
+    int count = (partialState >> STR_U_COUNT_SHIFT) & TWO_BIT_MASK;
+    for (int i = count; i < 4; i++, position++) {
+      if (position == chunkEnd) return chunkStringEscapeU(i, value);
+      int char = getChar(position);
+      int digit = parseHexDigit(char);
+      if (digit < 0) fail(position, "Invalid hex digit");
+      value = 16 * value + digit;
+    }
+    addCharToString(value);
+    return parseStringToBuffer(position);
+  }
+
+  /**
+   * Continues parsing a partial keyword.
+   */
+  int parsePartialKeyword(int position, int partialState) {
+    int keywordType = partialState & KWD_TYPE_MASK;
+    int count = partialState >> KWD_COUNT_SHIFT;
+    int keywordTypeIndex = keywordType >> KWD_TYPE_SHIFT;
+    String keyword =
+        const ["null", "true", "false", "\xEF\xBB\xBF"][keywordTypeIndex];
+    assert(count < keyword.length);
+    do {
+      if (position == chunkEnd) {
+        this.partialState =
+            PARTIAL_KEYWORD | keywordType | (count << KWD_COUNT_SHIFT);
+        return chunkEnd;
+      }
+      int expectedChar = keyword.codeUnitAt(count);
+      if (getChar(position) != expectedChar) {
+        if (count == 0) {
+          assert(keywordType == KWD_BOM);
+          return position;
+        }
+        return fail(position);
+      }
+      position++;
+      count++;
+    } while (count < keyword.length);
+    if (keywordType == KWD_NULL) {
+      listener.handleNull();
+    } else if (keywordType != KWD_BOM) {
+      listener.handleBool(keywordType == KWD_TRUE);
+    }
+    return position;
+  }
+
+  /** Convert hex-digit to its value. Returns -1 if char is not a hex digit. */
+  int parseHexDigit(int char) {
+    int digit = char ^ 0x30;
+    if (digit <= 9) return digit;
+    int letter = (char | 0x20) ^ 0x60;
+    // values 1 .. 6 are 'a' through 'f'
+    if (letter <= 6 && letter > 0) return letter + 9;
+    return -1;
+  }
+
+  /**
+   * Parses the current chunk as a chunk of JSON.
+   *
+   * Starts parsing at [position] and continues until [chunkEnd].
+   * Continues parsing where the previous chunk (if any) ended.
+   */
+  void parse(int position) {
+    int length = chunkEnd;
+    if (partialState != NO_PARTIAL) {
+      position = parsePartial(position);
+      if (position == length) return;
+    }
+    int state = this.state;
+    while (position < length) {
+      int char = getChar(position);
+      switch (char) {
+        case SPACE:
+        case CARRIAGE_RETURN:
+        case NEWLINE:
+        case TAB:
+          position++;
+          break;
+        case QUOTE:
+          if ((state & ALLOW_STRING_MASK) != 0) return fail(position);
+          state |= VALUE_READ_BITS;
+          position = parseString(position + 1);
+          break;
+        case LBRACKET:
+          if ((state & ALLOW_VALUE_MASK) != 0) return fail(position);
+          listener.beginArray();
+          saveState(state);
+          state = STATE_ARRAY_EMPTY;
+          position++;
+          break;
+        case LBRACE:
+          if ((state & ALLOW_VALUE_MASK) != 0) return fail(position);
+          listener.beginObject();
+          saveState(state);
+          state = STATE_OBJECT_EMPTY;
+          position++;
+          break;
+        case CHAR_n:
+          if ((state & ALLOW_VALUE_MASK) != 0) return fail(position);
+          state |= VALUE_READ_BITS;
+          position = parseNull(position);
+          break;
+        case CHAR_f:
+          if ((state & ALLOW_VALUE_MASK) != 0) return fail(position);
+          state |= VALUE_READ_BITS;
+          position = parseFalse(position);
+          break;
+        case CHAR_t:
+          if ((state & ALLOW_VALUE_MASK) != 0) return fail(position);
+          state |= VALUE_READ_BITS;
+          position = parseTrue(position);
+          break;
+        case COLON:
+          if (state != STATE_OBJECT_KEY) return fail(position);
+          listener.propertyName();
+          state = STATE_OBJECT_COLON;
+          position++;
+          break;
+        case COMMA:
+          if (state == STATE_OBJECT_VALUE) {
+            listener.propertyValue();
+            state = STATE_OBJECT_COMMA;
+            position++;
+          } else if (state == STATE_ARRAY_VALUE) {
+            listener.arrayElement();
+            state = STATE_ARRAY_COMMA;
+            position++;
+          } else {
+            return fail(position);
+          }
+          break;
+        case RBRACKET:
+          if (state == STATE_ARRAY_EMPTY) {
+            listener.endArray();
+          } else if (state == STATE_ARRAY_VALUE) {
+            listener.arrayElement();
+            listener.endArray();
+          } else {
+            return fail(position);
+          }
+          state = restoreState() | VALUE_READ_BITS;
+          position++;
+          break;
+        case RBRACE:
+          if (state == STATE_OBJECT_EMPTY) {
+            listener.endObject();
+          } else if (state == STATE_OBJECT_VALUE) {
+            listener.propertyValue();
+            listener.endObject();
+          } else {
+            return fail(position);
+          }
+          state = restoreState() | VALUE_READ_BITS;
+          position++;
+          break;
+        default:
+          if ((state & ALLOW_VALUE_MASK) != 0) fail(position);
+          state |= VALUE_READ_BITS;
+          position = parseNumber(char, position);
+          break;
+      }
+    }
+    this.state = state;
+  }
+
+  /**
+   * Parses a "true" literal starting at [position].
+   *
+   * The character `source[position]` must be "t".
+   */
+  int parseTrue(int position) {
+    assert(getChar(position) == CHAR_t);
+    if (chunkEnd < position + 4) {
+      return parseKeywordPrefix(position, "true", KWD_TRUE);
+    }
+    if (getChar(position + 1) != CHAR_r ||
+        getChar(position + 2) != CHAR_u ||
+        getChar(position + 3) != CHAR_e) {
+      return fail(position);
+    }
+    listener.handleBool(true);
+    return position + 4;
+  }
+
+  /**
+   * Parses a "false" literal starting at [position].
+   *
+   * The character `source[position]` must be "f".
+   */
+  int parseFalse(int position) {
+    assert(getChar(position) == CHAR_f);
+    if (chunkEnd < position + 5) {
+      return parseKeywordPrefix(position, "false", KWD_FALSE);
+    }
+    if (getChar(position + 1) != CHAR_a ||
+        getChar(position + 2) != CHAR_l ||
+        getChar(position + 3) != CHAR_s ||
+        getChar(position + 4) != CHAR_e) {
+      return fail(position);
+    }
+    listener.handleBool(false);
+    return position + 5;
+  }
+
+  /**
+   * Parses a "null" literal starting at [position].
+   *
+   * The character `source[position]` must be "n".
+   */
+  int parseNull(int position) {
+    assert(getChar(position) == CHAR_n);
+    if (chunkEnd < position + 4) {
+      return parseKeywordPrefix(position, "null", KWD_NULL);
+    }
+    if (getChar(position + 1) != CHAR_u ||
+        getChar(position + 2) != CHAR_l ||
+        getChar(position + 3) != CHAR_l) {
+      return fail(position);
+    }
+    listener.handleNull();
+    return position + 4;
+  }
+
+  int parseKeywordPrefix(int position, String chars, int type) {
+    assert(getChar(position) == chars.codeUnitAt(0));
+    int length = chunkEnd;
+    int start = position;
+    int count = 1;
+    while (++position < length) {
+      int char = getChar(position);
+      if (char != chars.codeUnitAt(count)) return fail(start);
+      count++;
+    }
+    this.partialState = PARTIAL_KEYWORD | type | (count << KWD_COUNT_SHIFT);
+    return length;
+  }
+
+  /**
+   * Parses a string value.
+   *
+   * Initial [position] is right after the initial quote.
+   * Returned position right after the final quote.
+   */
+  int parseString(int position) {
+    // Format: '"'([^\x00-\x1f\\\"]|'\\'[bfnrt/\\"])*'"'
+    // Initial position is right after first '"'.
+    int start = position;
+    int end = chunkEnd;
+    int bits = 0;
+    while (position < end) {
+      int char = getChar(position++);
+      bits |= char; // Includes final '"', but that never matters.
+      // BACKSLASH is larger than QUOTE and SPACE.
+      if (char > BACKSLASH) {
+        continue;
+      }
+      if (char == BACKSLASH) {
+        beginString();
+        int sliceEnd = position - 1;
+        if (start < sliceEnd) addSliceToString(start, sliceEnd);
+        return parseStringToBuffer(sliceEnd);
+      }
+      if (char == QUOTE) {
+        listener.handleString(getString(start, position - 1, bits));
+        return position;
+      }
+      if (char < SPACE) {
+        return fail(position - 1, "Control character in string");
+      }
+    }
+    beginString();
+    if (start < end) addSliceToString(start, end);
+    return chunkString(STR_PLAIN);
+  }
+
+  /**
+   * Sets up a partial string state.
+   *
+   * The state is either not inside an escape, or right after a backslash.
+   * For partial strings ending inside a Unicode escape, use
+   * [chunkStringEscapeU].
+   */
+  int chunkString(int stringState) {
+    partialState = PARTIAL_STRING | stringState;
+    return chunkEnd;
+  }
+
+  /**
+   * Sets up a partial string state for a partially parsed Unicode escape.
+   *
+   * The partial string state includes the current [buffer] and the
+   * number of hex digits of the Unicode seen so far (e.g., for `"\u30')
+   * the state knows that two digits have been seen, and what their value is.
+   *
+   * Returns [chunkEnd] so it can be used as part of a return statement.
+   */
+  int chunkStringEscapeU(int count, int value) {
+    partialState = PARTIAL_STRING |
+        STR_U |
+        (count << STR_U_COUNT_SHIFT) |
+        (value << STR_U_VALUE_SHIFT);
+    return chunkEnd;
+  }
+
+  /**
+   * Parses the remainder of a string literal into a buffer.
+   *
+   * The buffer is stored in [buffer] and its underlying format depends on
+   * the input chunk type. For example UTF-8 decoding happens in the
+   * buffer, not in the parser, since all significant JSON characters are ASCII.
+   *
+   * This function scans through the string literal for escapes, and copies
+   * slices of non-escape characters using [addSliceToString].
+   */
+  int parseStringToBuffer(int position) {
+    int end = chunkEnd;
+    int start = position;
+    while (true) {
+      if (position == end) {
+        if (position > start) {
+          addSliceToString(start, position);
+        }
+        return chunkString(STR_PLAIN);
+      }
+      int char = getChar(position++);
+      if (char > BACKSLASH) continue;
+      if (char < SPACE) {
+        return fail(position - 1); // Control character in string.
+      }
+      if (char == QUOTE) {
+        int quotePosition = position - 1;
+        if (quotePosition > start) {
+          addSliceToString(start, quotePosition);
+        }
+        listener.handleString(endString());
+        return position;
+      }
+      if (char != BACKSLASH) {
+        continue;
+      }
+      // Handle escape.
+      if (position - 1 > start) {
+        addSliceToString(start, position - 1);
+      }
+      if (position == end) return chunkString(STR_ESCAPE);
+      position = parseStringEscape(position);
+      if (position == end) return position;
+      start = position;
+    }
+    return -1; // UNREACHABLE.
+  }
+
+  /**
+   * Parse a string escape.
+   *
+   * Position is right after the initial backslash.
+   * The following escape is parsed into a character code which is added to
+   * the current string buffer using [addCharToString].
+   *
+   * Returns position after the last character of the escape.
+   */
+  int parseStringEscape(int position) {
+    int char = getChar(position++);
+    int length = chunkEnd;
+    switch (char) {
+      case CHAR_b:
+        char = BACKSPACE;
+        break;
+      case CHAR_f:
+        char = FORM_FEED;
+        break;
+      case CHAR_n:
+        char = NEWLINE;
+        break;
+      case CHAR_r:
+        char = CARRIAGE_RETURN;
+        break;
+      case CHAR_t:
+        char = TAB;
+        break;
+      case SLASH:
+      case BACKSLASH:
+      case QUOTE:
+        break;
+      case CHAR_u:
+        int hexStart = position - 1;
+        int value = 0;
+        for (int i = 0; i < 4; i++) {
+          if (position == length) return chunkStringEscapeU(i, value);
+          char = getChar(position++);
+          int digit = char ^ 0x30;
+          value *= 16;
+          if (digit <= 9) {
+            value += digit;
+          } else {
+            digit = (char | 0x20) - CHAR_a;
+            if (digit < 0 || digit > 5) {
+              return fail(hexStart, "Invalid unicode escape");
+            }
+            value += digit + 10;
+          }
+        }
+        char = value;
+        break;
+      default:
+        if (char < SPACE) return fail(position, "Control character in string");
+        return fail(position, "Unrecognized string escape");
+    }
+    addCharToString(char);
+    if (position == length) return chunkString(STR_PLAIN);
+    return position;
+  }
+
+  /// Sets up a partial numeral state.
+  /// Returns chunkEnd to allow easy one-line bailout tests.
+  int beginChunkNumber(int state, int start) {
+    int end = chunkEnd;
+    int length = end - start;
+    var buffer = new _NumberBuffer(length);
+    copyCharsToList(start, end, buffer.list, 0);
+    buffer.length = length;
+    this.buffer = buffer;
+    this.partialState = PARTIAL_NUMERAL | state;
+    return end;
+  }
+
+  void addNumberChunk(_NumberBuffer buffer, int start, int end, int overhead) {
+    int length = end - start;
+    int count = buffer.length;
+    int newCount = count + length;
+    int newCapacity = newCount + overhead;
+    buffer.ensureCapacity(newCapacity);
+    copyCharsToList(start, end, buffer.list, count);
+    buffer.length = newCount;
+  }
+
+  // Continues an already chunked number across an entire chunk.
+  int continueChunkNumber(int state, int start, _NumberBuffer buffer) {
+    int end = chunkEnd;
+    addNumberChunk(buffer, start, end, _NumberBuffer.kDefaultOverhead);
+    this.buffer = buffer;
+    this.partialState = PARTIAL_NUMERAL | state;
+    return end;
+  }
+
+  int finishChunkNumber(int state, int start, int end, _NumberBuffer buffer) {
+    if (state == NUM_ZERO) {
+      listener.handleNumber(0);
+      return end;
+    }
+    if (end > start) {
+      addNumberChunk(buffer, start, end, 0);
+    }
+    if (state == NUM_DIGIT) {
+      num value = buffer.parseNum();
+      listener.handleNumber(value);
+    } else if (state == NUM_DOT_DIGIT || state == NUM_E_DIGIT) {
+      listener.handleNumber(buffer.parseDouble());
+    } else {
+      fail(chunkEnd, "Unterminated number literal");
+    }
+    return end;
+  }
+
+  int parseNumber(int char, int position) {
+    // Also called on any unexpected character.
+    // Format:
+    //  '-'?('0'|[1-9][0-9]*)('.'[0-9]+)?([eE][+-]?[0-9]+)?
+    int start = position;
+    int length = chunkEnd;
+    // Collects an int value while parsing. Used for both an integer literal,
+    // and the exponent part of a double literal.
+    // Stored as negative to ensure we can represent -2^63.
+    int intValue = 0;
+    double doubleValue = 0.0; // Collect double value while parsing.
+    // 1 if there is no leading -, -1 if there is.
+    int sign = 1;
+    bool isDouble = false;
+    // Break this block when the end of the number literal is reached.
+    // At that time, position points to the next character, and isDouble
+    // is set if the literal contains a decimal point or an exponential.
+    if (char == MINUS) {
+      sign = -1;
+      position++;
+      if (position == length) return beginChunkNumber(NUM_SIGN, start);
+      char = getChar(position);
+    }
+    int digit = char ^ CHAR_0;
+    if (digit > 9) {
+      if (sign < 0) {
+        fail(position, "Missing expected digit");
+      } else {
+        // If it doesn't even start out as a numeral.
+        fail(position);
+      }
+    }
+    if (digit == 0) {
+      position++;
+      if (position == length) return beginChunkNumber(NUM_ZERO, start);
+      char = getChar(position);
+      digit = char ^ CHAR_0;
+      // If starting with zero, next character must not be digit.
+      if (digit <= 9) fail(position);
+    } else {
+      int digitCount = 0;
+      do {
+        if (digitCount >= 18) {
+          // Check for overflow.
+          // Is 1 if digit is 8 or 9 and sign == 0, or digit is 9 and sign < 0;
+          int highDigit = digit >> 3;
+          if (sign < 0) highDigit &= digit;
+          if (digitCount == 19 || intValue - highDigit < -922337203685477580) {
+            isDouble = true;
+            // Big value that we know is not trusted to be exact later,
+            // forcing reparsing using `double.parse`.
+            doubleValue = 9223372036854775808.0;
+          }
+        }
+        intValue = 10 * intValue - digit;
+        digitCount++;
+        position++;
+        if (position == length) return beginChunkNumber(NUM_DIGIT, start);
+        char = getChar(position);
+        digit = char ^ CHAR_0;
+      } while (digit <= 9);
+    }
+    if (char == DECIMALPOINT) {
+      if (!isDouble) {
+        isDouble = true;
+        doubleValue = (intValue == 0) ? 0.0 : -intValue.toDouble();
+      }
+      intValue = 0;
+      position++;
+      if (position == length) return beginChunkNumber(NUM_DOT, start);
+      char = getChar(position);
+      digit = char ^ CHAR_0;
+      if (digit > 9) fail(position);
+      do {
+        doubleValue = 10.0 * doubleValue + digit;
+        intValue -= 1;
+        position++;
+        if (position == length) return beginChunkNumber(NUM_DOT_DIGIT, start);
+        char = getChar(position);
+        digit = char ^ CHAR_0;
+      } while (digit <= 9);
+    }
+    if ((char | 0x20) == CHAR_e) {
+      if (!isDouble) {
+        isDouble = true;
+        doubleValue = (intValue == 0) ? 0.0 : -intValue.toDouble();
+        intValue = 0;
+      }
+      position++;
+      if (position == length) return beginChunkNumber(NUM_E, start);
+      char = getChar(position);
+      int expSign = 1;
+      int exponent = 0;
+      if (((char + 1) | 2) == 0x2e /*+ or -*/) {
+        expSign = 0x2C - char; // -1 for MINUS, +1 for PLUS
+        position++;
+        if (position == length) return beginChunkNumber(NUM_E_SIGN, start);
+        char = getChar(position);
+      }
+      digit = char ^ CHAR_0;
+      if (digit > 9) {
+        fail(position, "Missing expected digit");
+      }
+      bool exponentOverflow = false;
+      do {
+        exponent = 10 * exponent + digit;
+        if (exponent > 400) exponentOverflow = true;
+        position++;
+        if (position == length) return beginChunkNumber(NUM_E_DIGIT, start);
+        char = getChar(position);
+        digit = char ^ CHAR_0;
+      } while (digit <= 9);
+      if (exponentOverflow) {
+        if (doubleValue == 0.0 || expSign < 0) {
+          listener.handleNumber(sign < 0 ? -0.0 : 0.0);
+        } else {
+          listener.handleNumber(
+              sign < 0 ? double.negativeInfinity : double.infinity);
+        }
+        return position;
+      }
+      intValue += expSign * exponent;
+    }
+    if (!isDouble) {
+      int bitFlag = -(sign + 1) >> 1; // 0 if sign == -1, -1 if sign == 1
+      // Negate if bitFlag is -1 by doing ~intValue + 1
+      listener.handleNumber((intValue ^ bitFlag) - bitFlag);
+      return position;
+    }
+    // Double values at or above this value (2 ** 53) may have lost precision.
+    // Only trust results that are below this value.
+    const double maxExactDouble = 9007199254740992.0;
+    if (doubleValue < maxExactDouble) {
+      int exponent = intValue;
+      double signedMantissa = doubleValue * sign;
+      if (exponent >= -22) {
+        if (exponent < 0) {
+          listener.handleNumber(signedMantissa / POWERS_OF_TEN[-exponent]);
+          return position;
+        }
+        if (exponent == 0) {
+          listener.handleNumber(signedMantissa);
+          return position;
+        }
+        if (exponent <= 22) {
+          listener.handleNumber(signedMantissa * POWERS_OF_TEN[exponent]);
+          return position;
+        }
+      }
+    }
+    // If the value is outside the range +/-maxExactDouble or
+    // exponent is outside the range +/-22, then we can't trust simple double
+    // arithmetic to get the exact result, so we use the system double parsing.
+    listener.handleNumber(parseDouble(start, position));
+    return position;
+  }
+
+  fail(int position, [String message]) {
+    if (message == null) {
+      message = "Unexpected character";
+      if (position == chunkEnd) message = "Unexpected end of input";
+    }
+    throw new FormatException(message, chunk, position);
+  }
+}
+
+/**
+ * Chunked JSON parser that parses [String] chunks.
+ */
+class _JsonStringParser extends _ChunkedJsonParser<String> {
+  String chunk;
+  int chunkEnd;
+
+  _JsonStringParser(_JsonListener listener) : super(listener);
+
+  int getChar(int position) => chunk.codeUnitAt(position);
+
+  String getString(int start, int end, int bits) {
+    return chunk.substring(start, end);
+  }
+
+  void beginString() {
+    this.buffer = new StringBuffer();
+  }
+
+  void addSliceToString(int start, int end) {
+    StringBuffer buffer = this.buffer;
+    buffer.write(chunk.substring(start, end));
+  }
+
+  void addCharToString(int charCode) {
+    StringBuffer buffer = this.buffer;
+    buffer.writeCharCode(charCode);
+  }
+
+  String endString() {
+    StringBuffer buffer = this.buffer;
+    this.buffer = null;
+    return buffer.toString();
+  }
+
+  void copyCharsToList(int start, int end, List target, int offset) {
+    int length = end - start;
+    for (int i = 0; i < length; i++) {
+      target[offset + i] = chunk.codeUnitAt(start + i);
+    }
+  }
+
+  double parseDouble(int start, int end) {
+    return _parseDouble(chunk, start, end);
+  }
+}
+
+@patch
+class JsonDecoder {
+  @patch
+  StringConversionSink startChunkedConversion(Sink<Object> sink) {
+    return new _JsonStringDecoderSink(this._reviver, sink);
+  }
+}
+
+/**
+ * Implements the chunked conversion from a JSON string to its corresponding
+ * object.
+ *
+ * The sink only creates one object, but its input can be chunked.
+ */
+class _JsonStringDecoderSink extends StringConversionSinkBase {
+  _JsonStringParser _parser;
+  final Function(Object key, Object value) _reviver;
+  final Sink<Object> _sink;
+
+  _JsonStringDecoderSink(this._reviver, this._sink)
+      : _parser = _createParser(_reviver);
+
+  static _JsonStringParser _createParser(reviver) {
+    _BuildJsonListener listener;
+    if (reviver == null) {
+      listener = new _BuildJsonListener();
+    } else {
+      listener = new _ReviverJsonListener(reviver);
+    }
+    return new _JsonStringParser(listener);
+  }
+
+  void addSlice(String chunk, int start, int end, bool isLast) {
+    _parser.chunk = chunk;
+    _parser.chunkEnd = end;
+    _parser.parse(start);
+    if (isLast) _parser.close();
+  }
+
+  void add(String chunk) {
+    addSlice(chunk, 0, chunk.length, false);
+  }
+
+  void close() {
+    _parser.close();
+    var decoded = _parser.result;
+    _sink.add(decoded);
+    _sink.close();
+  }
+
+  ByteConversionSink asUtf8Sink(bool allowMalformed) {
+    _parser = null;
+    return new _JsonUtf8DecoderSink(_reviver, _sink, allowMalformed);
+  }
+}
+
+class _Utf8StringBuffer {
+  static const int INITIAL_CAPACITY = 32;
+  // Partial state encoding.
+  static const int MASK_TWO_BIT = 0x03;
+  static const int MASK_SIZE = MASK_TWO_BIT;
+  static const int SHIFT_MISSING = 2;
+  static const int SHIFT_VALUE = 4;
+  static const int NO_PARTIAL = 0;
+
+  // UTF-8 encoding and limits.
+  static const int MAX_ASCII = 127;
+  static const int MAX_TWO_BYTE = 0x7ff;
+  static const int MAX_THREE_BYTE = 0xffff;
+  static const int MAX_UNICODE = 0X10ffff;
+  static const int MASK_TWO_BYTE = 0x1f;
+  static const int MASK_THREE_BYTE = 0x0f;
+  static const int MASK_FOUR_BYTE = 0x07;
+  static const int MASK_CONTINUE_TAG = 0xC0;
+  static const int MASK_CONTINUE_VALUE = 0x3f;
+  static const int CONTINUE_TAG = 0x80;
+
+  // UTF-16 surrogate encoding.
+  static const int LEAD_SURROGATE = 0xD800;
+  static const int TAIL_SURROGATE = 0xDC00;
+  static const int SHIFT_HIGH_SURROGATE = 10;
+  static const int MASK_LOW_SURROGATE = 0x3ff;
+
+  // The internal buffer starts as Uint8List, but may change to Uint16List
+  // if the string contains non-Latin-1 characters.
+  List<int> buffer = new Uint8List(INITIAL_CAPACITY);
+  // Number of elements in buffer.
+  int length = 0;
+  // Partial decoding state, for cases where an UTF-8 sequences is split
+  // between chunks.
+  int partialState = NO_PARTIAL;
+  // Whether all characters so far have been Latin-1 (and the buffer is
+  // still a Uint8List). Set to false when the first non-Latin-1 character
+  // is encountered, and the buffer is then also converted to a Uint16List.
+  bool isLatin1 = true;
+  // If allowing malformed, invalid UTF-8 sequences are converted to
+  // U+FFFD.
+  bool allowMalformed;
+
+  _Utf8StringBuffer(this.allowMalformed);
+
+  /**
+   * Parse the continuation of a multi-byte UTF-8 sequence.
+   *
+   * Parse [utf8] from [position] to [end]. If the sequence extends beyond
+   * `end`, store the partial state in [partialState], and continue from there
+   * on the next added slice.
+   *
+   * The [size] is the number of expected continuation bytes total,
+   * and [missing] is the number of remaining continuation bytes.
+   * The [size] is used to detect overlong encodings.
+   * The [value] is the value collected so far.
+   *
+   * When called after seeing the first multi-byte marker, the [size] and
+   * [missing] values are always the same, but they may differ if continuing
+   * after a partial sequence.
+   */
+  int addContinuation(
+      List<int> utf8, int position, int end, int size, int missing, int value) {
+    int codeEnd = position + missing;
+    do {
+      if (position == end) {
+        missing = codeEnd - position;
+        partialState =
+            size | (missing << SHIFT_MISSING) | (value << SHIFT_VALUE);
+        return end;
+      }
+      int char = utf8[position];
+      if ((char & MASK_CONTINUE_TAG) != CONTINUE_TAG) {
+        if (allowMalformed) {
+          addCharCode(0xFFFD);
+          return position;
+        }
+        throw new FormatException(
+            "Expected UTF-8 continuation byte, "
+            "found $char",
+            utf8,
+            position);
+      }
+      value = 64 * value + (char & MASK_CONTINUE_VALUE);
+      position++;
+    } while (position < codeEnd);
+    if (value <= const [0, MAX_ASCII, MAX_TWO_BYTE, MAX_THREE_BYTE][size]) {
+      // Over-long encoding.
+      if (allowMalformed) {
+        value = 0xFFFD;
+      } else {
+        throw new FormatException(
+            "Invalid encoding: U+${value.toRadixString(16).padLeft(4, '0')}"
+            " encoded in ${size + 1} bytes.",
+            utf8,
+            position - 1);
+      }
+    }
+    addCharCode(value);
+    return position;
+  }
+
+  void addCharCode(int char) {
+    assert(char >= 0);
+    assert(char <= MAX_UNICODE);
+    if (partialState != NO_PARTIAL) {
+      if (allowMalformed) {
+        partialState = NO_PARTIAL;
+        addCharCode(0xFFFD);
+      } else {
+        throw new FormatException("Incomplete UTF-8 sequence");
+      }
+    }
+    if (isLatin1 && char > 0xff) {
+      _to16Bit(); // Also grows a little if close to full.
+    }
+    int length = this.length;
+    if (char <= MAX_THREE_BYTE) {
+      if (length == buffer.length) _grow();
+      buffer[length] = char;
+      this.length = length + 1;
+      return;
+    }
+    if (length + 2 > buffer.length) _grow();
+    int bits = char - 0x10000;
+    buffer[length] = LEAD_SURROGATE | (bits >> SHIFT_HIGH_SURROGATE);
+    buffer[length + 1] = TAIL_SURROGATE | (bits & MASK_LOW_SURROGATE);
+    this.length = length + 2;
+  }
+
+  void _to16Bit() {
+    assert(isLatin1);
+    Uint16List newBuffer;
+    if ((length + INITIAL_CAPACITY) * 2 <= buffer.length) {
+      // Reuse existing buffer if it's big enough.
+      newBuffer = new Uint16List.view((buffer as Uint8List).buffer);
+    } else {
+      int newCapacity = buffer.length;
+      if (newCapacity - length < INITIAL_CAPACITY) {
+        newCapacity = length + INITIAL_CAPACITY;
+      }
+      newBuffer = new Uint16List(newCapacity);
+    }
+    newBuffer.setRange(0, length, buffer);
+    buffer = newBuffer;
+    isLatin1 = false;
+  }
+
+  void _grow() {
+    int newCapacity = buffer.length * 2;
+    List newBuffer;
+    if (isLatin1) {
+      newBuffer = new Uint8List(newCapacity);
+    } else {
+      newBuffer = new Uint16List(newCapacity);
+    }
+    newBuffer.setRange(0, length, buffer);
+    buffer = newBuffer;
+  }
+
+  void addSlice(List<int> utf8, int position, int end) {
+    assert(position < end);
+    if (partialState > 0) {
+      int continueByteCount = (partialState & MASK_TWO_BIT);
+      int missing = (partialState >> SHIFT_MISSING) & MASK_TWO_BIT;
+      int value = partialState >> SHIFT_VALUE;
+      partialState = NO_PARTIAL;
+      position = addContinuation(
+          utf8, position, end, continueByteCount, missing, value);
+      if (position == end) return;
+    }
+    // Keep index and capacity in local variables while looping over
+    // ASCII characters.
+    int index = length;
+    int capacity = buffer.length;
+    while (position < end) {
+      int char = utf8[position];
+      if (char <= MAX_ASCII) {
+        if (index == capacity) {
+          length = index;
+          _grow();
+          capacity = buffer.length;
+        }
+        buffer[index++] = char;
+        position++;
+        continue;
+      }
+      length = index;
+      if ((char & MASK_CONTINUE_TAG) == CONTINUE_TAG) {
+        if (allowMalformed) {
+          addCharCode(0xFFFD);
+          position++;
+        } else {
+          throw new FormatException(
+              "Unexpected UTF-8 continuation byte", utf8, position);
+        }
+      } else if (char < 0xE0) {
+        // C0-DF
+        // Two-byte.
+        position = addContinuation(
+            utf8, position + 1, end, 1, 1, char & MASK_TWO_BYTE);
+      } else if (char < 0xF0) {
+        // E0-EF
+        // Three-byte.
+        position = addContinuation(
+            utf8, position + 1, end, 2, 2, char & MASK_THREE_BYTE);
+      } else if (char < 0xF8) {
+        // F0-F7
+        // Four-byte.
+        position = addContinuation(
+            utf8, position + 1, end, 3, 3, char & MASK_FOUR_BYTE);
+      } else {
+        if (allowMalformed) {
+          addCharCode(0xFFFD);
+          position++;
+        } else {
+          throw new FormatException(
+              "Invalid UTF-8 byte: $char", utf8, position);
+        }
+      }
+      index = length;
+      capacity = buffer.length;
+    }
+    length = index;
+  }
+
+  String toString() {
+    if (partialState != NO_PARTIAL) {
+      if (allowMalformed) {
+        partialState = NO_PARTIAL;
+        addCharCode(0xFFFD);
+      } else {
+        int continueByteCount = (partialState & MASK_TWO_BIT);
+        int missing = (partialState >> SHIFT_MISSING) & MASK_TWO_BIT;
+        int value = partialState >> SHIFT_VALUE;
+        int seenByteCount = continueByteCount - missing + 1;
+        List source = new Uint8List(seenByteCount);
+        while (seenByteCount > 1) {
+          seenByteCount--;
+          source[seenByteCount] = CONTINUE_TAG | (value & MASK_CONTINUE_VALUE);
+          value >>= 6;
+        }
+        source[0] = value | (0x3c0 >> (continueByteCount - 1));
+        throw new FormatException(
+            "Incomplete UTF-8 sequence", source, source.length);
+      }
+    }
+    return new String.fromCharCodes(buffer, 0, length);
+  }
+}
+
+/**
+ * Chunked JSON parser that parses UTF-8 chunks.
+ */
+class _JsonUtf8Parser extends _ChunkedJsonParser<List<int>> {
+  final bool allowMalformed;
+  List<int> chunk;
+  int chunkEnd;
+
+  _JsonUtf8Parser(_JsonListener listener, this.allowMalformed)
+      : super(listener) {
+    // Starts out checking for an optional BOM (KWD_BOM, count = 0).
+    partialState =
+        _ChunkedJsonParser.PARTIAL_KEYWORD | _ChunkedJsonParser.KWD_BOM;
+  }
+
+  int getChar(int position) => chunk[position];
+
+  String getString(int start, int end, int bits) {
+    const int maxAsciiChar = 0x7f;
+    if (bits <= maxAsciiChar) {
+      return new String.fromCharCodes(chunk, start, end);
+    }
+    beginString();
+    if (start < end) addSliceToString(start, end);
+    String result = endString();
+    return result;
+  }
+
+  void beginString() {
+    this.buffer = new _Utf8StringBuffer(allowMalformed);
+  }
+
+  void addSliceToString(int start, int end) {
+    _Utf8StringBuffer buffer = this.buffer;
+    buffer.addSlice(chunk, start, end);
+  }
+
+  void addCharToString(int charCode) {
+    _Utf8StringBuffer buffer = this.buffer;
+    buffer.addCharCode(charCode);
+  }
+
+  String endString() {
+    _Utf8StringBuffer buffer = this.buffer;
+    this.buffer = null;
+    return buffer.toString();
+  }
+
+  void copyCharsToList(int start, int end, List target, int offset) {
+    int length = end - start;
+    target.setRange(offset, offset + length, chunk, start);
+  }
+
+  double parseDouble(int start, int end) {
+    String string = getString(start, end, 0x7f);
+    return _parseDouble(string, 0, string.length);
+  }
+}
+
+double _parseDouble(String source, int start, int end) native "Double_parse";
+
+/**
+ * Implements the chunked conversion from a UTF-8 encoding of JSON
+ * to its corresponding object.
+ */
+class _JsonUtf8DecoderSink extends ByteConversionSinkBase {
+  final _JsonUtf8Parser _parser;
+  final Sink<Object> _sink;
+
+  _JsonUtf8DecoderSink(reviver, this._sink, bool allowMalformed)
+      : _parser = _createParser(reviver, allowMalformed);
+
+  static _JsonUtf8Parser _createParser(reviver, bool allowMalformed) {
+    _BuildJsonListener listener;
+    if (reviver == null) {
+      listener = new _BuildJsonListener();
+    } else {
+      listener = new _ReviverJsonListener(reviver);
+    }
+    return new _JsonUtf8Parser(listener, allowMalformed);
+  }
+
+  void addSlice(List<int> chunk, int start, int end, bool isLast) {
+    _addChunk(chunk, start, end);
+    if (isLast) close();
+  }
+
+  void add(List<int> chunk) {
+    _addChunk(chunk, 0, chunk.length);
+  }
+
+  void _addChunk(List<int> chunk, int start, int end) {
+    _parser.chunk = chunk;
+    _parser.chunkEnd = end;
+    _parser.parse(start);
+  }
+
+  void close() {
+    _parser.close();
+    var decoded = _parser.result;
+    _sink.add(decoded);
+    _sink.close();
+  }
+}
+
+@patch
+int _scanOneByteCharacters(List<int> units, int from, int endIndex) {
+  final to = endIndex;
+
+  // Special case for _Uint8ArrayView.
+  if (units is Uint8List) {
+    if (from >= 0 && to >= 0 && to <= units.length) {
+      for (int i = from; i < to; i++) {
+        final unit = units[i];
+        if ((unit & _ONE_BYTE_LIMIT) != unit) return i - from;
+      }
+      return to - from;
+    }
+  }
+
+  // Fall through to normal case.
+  for (var i = from; i < to; i++) {
+    final unit = units[i];
+    if ((unit & _ONE_BYTE_LIMIT) != unit) return i - from;
+  }
+  return to - from;
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/core_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/core_patch.dart
new file mode 100644
index 0000000..bcfe3be
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/core_patch.dart
@@ -0,0 +1,168 @@
+// 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
+
+/// Note: the VM concatenates all patch files into a single patch file. This
+/// file is the first patch in "dart:core" which contains all the imports
+/// used by patches of that library. We plan to change this when we have a
+/// shared front end and simply use parts.
+
+import "dart:_internal" as internal show Symbol;
+
+import "dart:_internal"
+    show
+        ClassID,
+        CodeUnits,
+        EfficientLengthIterable,
+        FixedLengthListBase,
+        IterableElementError,
+        ListIterator,
+        Lists,
+        POWERS_OF_TEN,
+        SubListIterable,
+        UnmodifiableListBase,
+        is64Bit,
+        makeFixedListUnmodifiable,
+        makeListFixedLength,
+        patch,
+        unsafeCast;
+
+import "dart:async" show Completer, Future, Timer;
+
+import "dart:collection"
+    show
+        HashMap,
+        IterableBase,
+        LinkedHashMap,
+        LinkedList,
+        LinkedListEntry,
+        ListBase,
+        MapBase,
+        Maps,
+        UnmodifiableMapBase,
+        UnmodifiableMapView;
+
+import "dart:convert" show ascii, Encoding, json, latin1, utf8;
+
+import "dart:isolate" show Isolate;
+
+import "dart:math" show Random;
+
+import "dart:typed_data"
+    show Endian, Uint8List, Int64List, Uint16List, Uint32List;
+
+/// These are the additional parts of this patch library:
+// part "array.dart";
+// part "array_patch.dart";
+// part "bigint_patch.dart";
+// part "bool_patch.dart";
+// part "date_patch.dart";
+// part "double.dart";
+// part "double_patch.dart";
+// part "errors_patch.dart";
+// part "expando_patch.dart";
+// part "function.dart";
+// part "function_patch.dart";
+// part "growable_array.dart";
+// part "identical_patch.dart";
+// part "immutable_map.dart";
+// part "integers.dart";
+// part "integers_patch.dart";
+// part "invocation_mirror_patch.dart";
+// part "lib_prefix.dart";
+// part "map_patch.dart";
+// part "null_patch.dart";
+// part "object_patch.dart";
+// part "regexp_patch.dart";
+// part "stacktrace.dart";
+// part "stopwatch_patch.dart";
+// part "string_buffer_patch.dart";
+// part "string_patch.dart";
+// part "type_patch.dart";
+// part "uri_patch.dart";
+// part "weak_property.dart";
+
+@patch
+class num {
+  num _addFromInteger(int other);
+  num _subFromInteger(int other);
+  num _mulFromInteger(int other);
+  int _truncDivFromInteger(int other);
+  num _moduloFromInteger(int other);
+  num _remainderFromInteger(int other);
+  bool _greaterThanFromInteger(int other);
+  bool _equalToInteger(int other);
+}
+
+// _SyncIterable and _syncIterator are used by the compiler to
+// implement sync* generator functions. A sync* generator allocates
+// and returns a new _SyncIterable object.
+
+typedef bool _SyncGeneratorCallback<T>(_SyncIterator<T> iterator);
+
+class _SyncIterable<T> extends IterableBase<T> {
+  // _moveNextFn is the closurized body of the generator function.
+  final _SyncGeneratorCallback<T> _moveNextFn;
+
+  const _SyncIterable(this._moveNextFn);
+
+  Iterator<T> get iterator {
+    // Note: _Closure._clone returns _Closure which is not related to
+    // _SyncGeneratorCallback, which means we need explicit cast.
+    return new _SyncIterator<T>(unsafeCast<_SyncGeneratorCallback<T>>(
+        unsafeCast<_Closure>(_moveNextFn)._clone()));
+  }
+}
+
+class _SyncIterator<T> implements Iterator<T> {
+  _SyncGeneratorCallback<T> _moveNextFn;
+  Iterator<T> _yieldEachIterator;
+
+  // These two fields are set by generated code for the yield and yield*
+  // statement.
+  T _current;
+  Iterable<T> _yieldEachIterable;
+
+  T get current =>
+      _yieldEachIterator != null ? _yieldEachIterator.current : _current;
+
+  _SyncIterator(this._moveNextFn);
+
+  bool moveNext() {
+    if (_moveNextFn == null) {
+      return false;
+    }
+    while (true) {
+      if (_yieldEachIterator != null) {
+        if (_yieldEachIterator.moveNext()) {
+          return true;
+        }
+        _yieldEachIterator = null;
+      }
+      // _moveNextFn() will update the values of _yieldEachIterable
+      //  and _current.
+      if (!_moveNextFn(this)) {
+        _moveNextFn = null;
+        _current = null;
+        return false;
+      }
+      if (_yieldEachIterable != null) {
+        // Spec mandates: it is a dynamic error if the class of [the object
+        // returned by yield*] does not implement Iterable.
+        _yieldEachIterator = _yieldEachIterable.iterator;
+        _yieldEachIterable = null;
+        _current = null;
+        continue;
+      }
+      return true;
+    }
+  }
+}
+
+@patch
+class StackTrace {
+  @patch
+  static StackTrace get current native "StackTrace_current";
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/date_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/date_patch.dart
new file mode 100644
index 0000000..a53cba1
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/date_patch.dart
@@ -0,0 +1,448 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+// VM implementation of DateTime.
+@patch
+class DateTime {
+  // Natives.
+  // The natives have been moved up here to work around Issue 10401.
+  static int _getCurrentMicros() native "DateTime_currentTimeMicros";
+
+  static String _timeZoneNameForClampedSeconds(int secondsSinceEpoch)
+      native "DateTime_timeZoneName";
+
+  static int _timeZoneOffsetInSecondsForClampedSeconds(int secondsSinceEpoch)
+      native "DateTime_timeZoneOffsetInSeconds";
+
+  static int _localTimeZoneAdjustmentInSeconds()
+      native "DateTime_localTimeZoneAdjustmentInSeconds";
+
+  static const _MICROSECOND_INDEX = 0;
+  static const _MILLISECOND_INDEX = 1;
+  static const _SECOND_INDEX = 2;
+  static const _MINUTE_INDEX = 3;
+  static const _HOUR_INDEX = 4;
+  static const _DAY_INDEX = 5;
+  static const _WEEKDAY_INDEX = 6;
+  static const _MONTH_INDEX = 7;
+  static const _YEAR_INDEX = 8;
+
+  List __parts;
+
+  @patch
+  DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch,
+      {bool isUtc: false})
+      : this._withValue(
+            millisecondsSinceEpoch * Duration.microsecondsPerMillisecond,
+            isUtc: isUtc);
+
+  @patch
+  DateTime.fromMicrosecondsSinceEpoch(int microsecondsSinceEpoch,
+      {bool isUtc: false})
+      : this._withValue(microsecondsSinceEpoch, isUtc: isUtc);
+
+  @patch
+  DateTime._internal(int year, int month, int day, int hour, int minute,
+      int second, int millisecond, int microsecond, bool isUtc)
+      : this.isUtc = isUtc,
+        this._value = _brokenDownDateToValue(year, month, day, hour, minute,
+            second, millisecond, microsecond, isUtc) {
+    if (_value == null) throw new ArgumentError();
+    if (isUtc == null) throw new ArgumentError();
+  }
+
+  @patch
+  DateTime._now()
+      : isUtc = false,
+        _value = _getCurrentMicros();
+
+  @patch
+  String get timeZoneName {
+    if (isUtc) return "UTC";
+    return _timeZoneName(microsecondsSinceEpoch);
+  }
+
+  @patch
+  Duration get timeZoneOffset {
+    if (isUtc) return new Duration();
+    int offsetInSeconds = _timeZoneOffsetInSeconds(microsecondsSinceEpoch);
+    return new Duration(seconds: offsetInSeconds);
+  }
+
+  @patch
+  bool operator ==(dynamic other) =>
+      other is DateTime &&
+      _value == other.microsecondsSinceEpoch &&
+      isUtc == other.isUtc;
+
+  @patch
+  bool isBefore(DateTime other) => _value < other.microsecondsSinceEpoch;
+
+  @patch
+  bool isAfter(DateTime other) => _value > other.microsecondsSinceEpoch;
+
+  @patch
+  bool isAtSameMomentAs(DateTime other) =>
+      _value == other.microsecondsSinceEpoch;
+
+  @patch
+  int compareTo(DateTime other) =>
+      _value.compareTo(other.microsecondsSinceEpoch);
+
+  /** The first list contains the days until each month in non-leap years. The
+    * second list contains the days in leap years. */
+  static const List<List<int>> _DAYS_UNTIL_MONTH = const [
+    const [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
+    const [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335]
+  ];
+
+  static List _computeUpperPart(int localMicros) {
+    const int DAYS_IN_4_YEARS = 4 * 365 + 1;
+    const int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1;
+    const int DAYS_IN_400_YEARS = 4 * DAYS_IN_100_YEARS + 1;
+    const int DAYS_1970_TO_2000 = 30 * 365 + 7;
+    const int DAYS_OFFSET =
+        1000 * DAYS_IN_400_YEARS + 5 * DAYS_IN_400_YEARS - DAYS_1970_TO_2000;
+    const int YEARS_OFFSET = 400000;
+
+    int resultYear = 0;
+    int resultMonth = 0;
+    int resultDay = 0;
+
+    // Always round down.
+    final int daysSince1970 =
+        _flooredDivision(localMicros, Duration.microsecondsPerDay);
+    int days = daysSince1970;
+    days += DAYS_OFFSET;
+    resultYear = 400 * (days ~/ DAYS_IN_400_YEARS) - YEARS_OFFSET;
+    days = days.remainder(DAYS_IN_400_YEARS);
+    days--;
+    int yd1 = days ~/ DAYS_IN_100_YEARS;
+    days = days.remainder(DAYS_IN_100_YEARS);
+    resultYear += 100 * yd1;
+    days++;
+    int yd2 = days ~/ DAYS_IN_4_YEARS;
+    days = days.remainder(DAYS_IN_4_YEARS);
+    resultYear += 4 * yd2;
+    days--;
+    int yd3 = days ~/ 365;
+    days = days.remainder(365);
+    resultYear += yd3;
+
+    bool isLeap = (yd1 == 0 || yd2 != 0) && yd3 == 0;
+    if (isLeap) days++;
+
+    List<int> daysUntilMonth = _DAYS_UNTIL_MONTH[isLeap ? 1 : 0];
+    for (resultMonth = 12;
+        daysUntilMonth[resultMonth - 1] > days;
+        resultMonth--) {
+      // Do nothing.
+    }
+    resultDay = days - daysUntilMonth[resultMonth - 1] + 1;
+
+    int resultMicrosecond = localMicros % Duration.microsecondsPerMillisecond;
+    int resultMillisecond =
+        _flooredDivision(localMicros, Duration.microsecondsPerMillisecond) %
+            Duration.millisecondsPerSecond;
+    int resultSecond =
+        _flooredDivision(localMicros, Duration.microsecondsPerSecond) %
+            Duration.secondsPerMinute;
+
+    int resultMinute =
+        _flooredDivision(localMicros, Duration.microsecondsPerMinute);
+    resultMinute %= Duration.minutesPerHour;
+
+    int resultHour =
+        _flooredDivision(localMicros, Duration.microsecondsPerHour);
+    resultHour %= Duration.hoursPerDay;
+
+    // In accordance with ISO 8601 a week
+    // starts with Monday. Monday has the value 1 up to Sunday with 7.
+    // 1970-1-1 was a Thursday.
+    int resultWeekday = ((daysSince1970 + DateTime.thursday - DateTime.monday) %
+            DateTime.daysPerWeek) +
+        DateTime.monday;
+
+    List list = new List(_YEAR_INDEX + 1);
+    list[_MICROSECOND_INDEX] = resultMicrosecond;
+    list[_MILLISECOND_INDEX] = resultMillisecond;
+    list[_SECOND_INDEX] = resultSecond;
+    list[_MINUTE_INDEX] = resultMinute;
+    list[_HOUR_INDEX] = resultHour;
+    list[_DAY_INDEX] = resultDay;
+    list[_WEEKDAY_INDEX] = resultWeekday;
+    list[_MONTH_INDEX] = resultMonth;
+    list[_YEAR_INDEX] = resultYear;
+    return list;
+  }
+
+  get _parts {
+    __parts ??= _computeUpperPart(_localDateInUtcMicros);
+    return __parts;
+  }
+
+  @patch
+  DateTime add(Duration duration) {
+    return new DateTime._withValue(_value + duration.inMicroseconds,
+        isUtc: isUtc);
+  }
+
+  @patch
+  DateTime subtract(Duration duration) {
+    return new DateTime._withValue(_value - duration.inMicroseconds,
+        isUtc: isUtc);
+  }
+
+  @patch
+  Duration difference(DateTime other) {
+    return new Duration(microseconds: _value - other._value);
+  }
+
+  @patch
+  int get millisecondsSinceEpoch =>
+      _value ~/ Duration.microsecondsPerMillisecond;
+
+  @patch
+  int get microsecondsSinceEpoch => _value;
+
+  @patch
+  int get microsecond => _parts[_MICROSECOND_INDEX];
+
+  @patch
+  int get millisecond => _parts[_MILLISECOND_INDEX];
+
+  @patch
+  int get second => _parts[_SECOND_INDEX];
+
+  @patch
+  int get minute => _parts[_MINUTE_INDEX];
+
+  @patch
+  int get hour => _parts[_HOUR_INDEX];
+
+  @patch
+  int get day => _parts[_DAY_INDEX];
+
+  @patch
+  int get weekday => _parts[_WEEKDAY_INDEX];
+
+  @patch
+  int get month => _parts[_MONTH_INDEX];
+
+  @patch
+  int get year => _parts[_YEAR_INDEX];
+
+  /**
+   * Returns the amount of microseconds in UTC that represent the same values
+   * as [this].
+   *
+   * Say `t` is the result of this function, then
+   * * `this.year == new DateTime.fromMicrosecondsSinceEpoch(t, true).year`,
+   * * `this.month == new DateTime.fromMicrosecondsSinceEpoch(t, true).month`,
+   * * `this.day == new DateTime.fromMicrosecondsSinceEpoch(t, true).day`,
+   * * `this.hour == new DateTime.fromMicrosecondsSinceEpoch(t, true).hour`,
+   * * ...
+   *
+   * Daylight savings is computed as if the date was computed in [1970..2037].
+   * If [this] lies outside this range then it is a year with similar
+   * properties (leap year, weekdays) is used instead.
+   */
+  int get _localDateInUtcMicros {
+    int micros = _value;
+    if (isUtc) return micros;
+    int offset =
+        _timeZoneOffsetInSeconds(micros) * Duration.microsecondsPerSecond;
+    return micros + offset;
+  }
+
+  static int _flooredDivision(int a, int b) {
+    return (a - (a < 0 ? b - 1 : 0)) ~/ b;
+  }
+
+  // Returns the days since 1970 for the start of the given [year].
+  // [year] may be before epoch.
+  static int _dayFromYear(int year) {
+    return 365 * (year - 1970) +
+        _flooredDivision(year - 1969, 4) -
+        _flooredDivision(year - 1901, 100) +
+        _flooredDivision(year - 1601, 400);
+  }
+
+  static bool _isLeapYear(y) {
+    // (y % 16 == 0) matches multiples of 400, and is faster than % 400.
+    return (y % 4 == 0) && ((y % 16 == 0) || (y % 100 != 0));
+  }
+
+  /// Converts the given broken down date to microseconds.
+  @patch
+  static int _brokenDownDateToValue(int year, int month, int day, int hour,
+      int minute, int second, int millisecond, int microsecond, bool isUtc) {
+    // Simplify calculations by working with zero-based month.
+    --month;
+    // Deal with under and overflow.
+    if (month >= 12) {
+      year += month ~/ 12;
+      month = month % 12;
+    } else if (month < 0) {
+      int realMonth = month % 12;
+      year += (month - realMonth) ~/ 12;
+      month = realMonth;
+    }
+
+    // First compute the seconds in UTC, independent of the [isUtc] flag. If
+    // necessary we will add the time-zone offset later on.
+    int days = day - 1;
+    days += _DAYS_UNTIL_MONTH[_isLeapYear(year) ? 1 : 0][month];
+    days += _dayFromYear(year);
+    int microsecondsSinceEpoch = days * Duration.microsecondsPerDay +
+        hour * Duration.microsecondsPerHour +
+        minute * Duration.microsecondsPerMinute +
+        second * Duration.microsecondsPerSecond +
+        millisecond * Duration.microsecondsPerMillisecond +
+        microsecond;
+
+    // Since [_timeZoneOffsetInSeconds] will crash if the input is far out of
+    // the valid range we do a preliminary test that weeds out values that can
+    // not become valid even with timezone adjustments.
+    // The timezone adjustment is always less than a day, so adding a security
+    // margin of one day should be enough.
+    if (microsecondsSinceEpoch.abs() >
+        _maxMillisecondsSinceEpoch * 1000 + Duration.microsecondsPerDay) {
+      return null;
+    }
+
+    if (!isUtc) {
+      // Note that we can't literally follow the ECMAScript spec (which this
+      // code is based on), because it leads to incorrect computations at
+      // the DST transition points.
+      //
+      // See V8's comment here:
+      // https://github.com/v8/v8/blob/089dd7d2447d6eaf57c8ba6d8f37957f3a269777/src/date.h#L118
+
+      // We need to remove the local timezone adjustment before asking for the
+      // correct zone offset.
+      int adjustment =
+          _localTimeZoneAdjustmentInSeconds() * Duration.microsecondsPerSecond;
+      // The adjustment is independent of the actual date and of the daylight
+      // saving time. It is positive east of the Prime Meridian and negative
+      // west of it, e.g. -28800 sec for America/Los_Angeles timezone.
+
+      // We remove one hour to ensure that we have the correct offset at
+      // DST transitioning points. This is a temporary solution and only
+      // correct in timezones that shift for exactly one hour.
+      adjustment += Duration.microsecondsPerHour;
+      int zoneOffset =
+          _timeZoneOffsetInSeconds(microsecondsSinceEpoch - adjustment);
+
+      // The zoneOffset depends on the actual date and reflects any daylight
+      // saving time and/or historical deviation relative to UTC time.
+      // It is positive east of the Prime Meridian and negative west of it,
+      // e.g. -25200 sec for America/Los_Angeles timezone during DST.
+      microsecondsSinceEpoch -= zoneOffset * Duration.microsecondsPerSecond;
+      // The resulting microsecondsSinceEpoch value is therefore the calculated
+      // UTC value decreased by a (positive if east of GMT) timezone adjustment
+      // and decreased by typically one hour if DST is in effect.
+    }
+    if (microsecondsSinceEpoch.abs() >
+        _maxMillisecondsSinceEpoch * Duration.microsecondsPerMillisecond) {
+      return null;
+    }
+    return microsecondsSinceEpoch;
+  }
+
+  static int _weekDay(y) {
+    // 1/1/1970 was a Thursday.
+    return (_dayFromYear(y) + 4) % 7;
+  }
+
+  /**
+   * Returns a year in the range 2008-2035 matching
+   * * leap year, and
+   * * week day of first day.
+   *
+   * Leap seconds are ignored.
+   * Adapted from V8's date implementation. See ECMA 262 - 15.9.1.9.
+   */
+  static int _equivalentYear(int year) {
+    // Returns year y so that _weekDay(y) == _weekDay(year).
+    // _weekDay returns the week day (in range 0 - 6).
+    // 1/1/1956 was a Sunday (i.e. weekday 0). 1956 was a leap-year.
+    // 1/1/1967 was a Sunday (i.e. weekday 0).
+    // Without leap years a subsequent year has a week day + 1 (for example
+    // 1/1/1968 was a Monday). With leap-years it jumps over one week day
+    // (e.g. 1/1/1957 was a Tuesday).
+    // After 12 years the weekdays have advanced by 12 days + 3 leap days =
+    // 15 days. 15 % 7 = 1. So after 12 years the week day has always
+    // (now independently of leap-years) advanced by one.
+    // weekDay * 12 gives thus a year starting with the wanted weekDay.
+    int recentYear = (_isLeapYear(year) ? 1956 : 1967) + (_weekDay(year) * 12);
+    // Close to the year 2008 the calendar cycles every 4 * 7 years (4 for the
+    // leap years, 7 for the weekdays).
+    // Find the year in the range 2008..2037 that is equivalent mod 28.
+    return 2008 + (recentYear - 2008) % 28;
+  }
+
+  /**
+   * Returns the UTC year for the corresponding [secondsSinceEpoch].
+   * It is relatively fast for values in the range 0 to year 2098.
+   *
+   * Code is adapted from V8.
+   */
+  static int _yearsFromSecondsSinceEpoch(int secondsSinceEpoch) {
+    const int DAYS_IN_4_YEARS = 4 * 365 + 1;
+    const int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1;
+    const int DAYS_YEAR_2098 = DAYS_IN_100_YEARS + 6 * DAYS_IN_4_YEARS;
+
+    int days = secondsSinceEpoch ~/ Duration.secondsPerDay;
+    if (days > 0 && days < DAYS_YEAR_2098) {
+      // According to V8 this fast case works for dates from 1970 to 2099.
+      return 1970 + (4 * days + 2) ~/ DAYS_IN_4_YEARS;
+    }
+    int micros = secondsSinceEpoch * Duration.microsecondsPerSecond;
+    return _computeUpperPart(micros)[_YEAR_INDEX];
+  }
+
+  /**
+   * Returns a date in seconds that is equivalent to the given
+   * date in microseconds [microsecondsSinceEpoch]. An equivalent
+   * date has the same fields (`month`, `day`, etc.) as the given
+   * date, but the `year` is in the range [1901..2038].
+   *
+   * * The time since the beginning of the year is the same.
+   * * If the given date is in a leap year then the returned
+   *   seconds are in a leap year, too.
+   * * The week day of given date is the same as the one for the
+   *   returned date.
+   */
+  static int _equivalentSeconds(int microsecondsSinceEpoch) {
+    const int CUT_OFF_SECONDS = 0x7FFFFFFF;
+
+    int secondsSinceEpoch = _flooredDivision(
+        microsecondsSinceEpoch, Duration.microsecondsPerSecond);
+
+    if (secondsSinceEpoch.abs() > CUT_OFF_SECONDS) {
+      int year = _yearsFromSecondsSinceEpoch(secondsSinceEpoch);
+      int days = _dayFromYear(year);
+      int equivalentYear = _equivalentYear(year);
+      int equivalentDays = _dayFromYear(equivalentYear);
+      int diffDays = equivalentDays - days;
+      secondsSinceEpoch += diffDays * Duration.secondsPerDay;
+    }
+    return secondsSinceEpoch;
+  }
+
+  static int _timeZoneOffsetInSeconds(int microsecondsSinceEpoch) {
+    int equivalentSeconds = _equivalentSeconds(microsecondsSinceEpoch);
+    return _timeZoneOffsetInSecondsForClampedSeconds(equivalentSeconds);
+  }
+
+  static String _timeZoneName(int microsecondsSinceEpoch) {
+    int equivalentSeconds = _equivalentSeconds(microsecondsSinceEpoch);
+    return _timeZoneNameForClampedSeconds(equivalentSeconds);
+  }
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/deferred_load_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/deferred_load_patch.dart
new file mode 100644
index 0000000..3651d7e
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/deferred_load_patch.dart
@@ -0,0 +1,21 @@
+// 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 "async_patch.dart";
+
+final Set<String> _loadedLibraries = new Set<String>();
+
+@patch
+class DeferredLibrary {
+  @patch
+  Future<Null> load() {
+    // Dummy implementation that should eventually be replaced by real
+    // implementation.
+    Future future = new Future<Null>.value(null);
+    _loadedLibraries.add(libraryName);
+    return future;
+  }
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/developer.dart b/sdk_nnbd/lib/_internal/vm/lib/developer.dart
new file mode 100644
index 0000000..538303d
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/developer.dart
@@ -0,0 +1,171 @@
+// 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.
+
+// @dart = 2.5
+
+/// Note: the VM concatenates all patch files into a single patch file. This
+/// file is the first patch in "dart:developer" which contains all the imports
+/// used by patches of that library. We plan to change this when we have a
+/// shared front end and simply use parts.
+
+import "dart:_internal" show patch;
+
+import "dart:async" show Future, Zone;
+
+import "dart:isolate" show SendPort;
+
+/// These are the additional parts of this patch library:
+// part "profiler.dart"
+// part "timeline.dart"
+
+@patch
+bool debugger({bool when: true, String message}) native "Developer_debugger";
+
+@patch
+Object inspect(Object object) native "Developer_inspect";
+
+@patch
+void log(String message,
+    {DateTime time,
+    int sequenceNumber,
+    int level: 0,
+    String name: '',
+    Zone zone,
+    Object error,
+    StackTrace stackTrace}) {
+  if (message is! String) {
+    throw new ArgumentError.value(message, "message", "Must be a String");
+  }
+  time ??= new DateTime.now();
+  if (time is! DateTime) {
+    throw new ArgumentError.value(time, "time", "Must be a DateTime");
+  }
+  if (sequenceNumber == null) {
+    sequenceNumber = _nextSequenceNumber++;
+  } else {
+    _nextSequenceNumber = sequenceNumber + 1;
+  }
+  _log(message, time.millisecondsSinceEpoch, sequenceNumber, level, name, zone,
+      error, stackTrace);
+}
+
+int _nextSequenceNumber = 0;
+
+_log(String message, int timestamp, int sequenceNumber, int level, String name,
+    Zone zone, Object error, StackTrace stackTrace) native "Developer_log";
+
+@patch
+void _postEvent(String eventKind, String eventData)
+    native "Developer_postEvent";
+
+@patch
+ServiceExtensionHandler _lookupExtension(String method)
+    native "Developer_lookupExtension";
+
+@patch
+_registerExtension(String method, ServiceExtensionHandler handler)
+    native "Developer_registerExtension";
+
+// This code is only invoked when there is no other Dart code on the stack.
+@pragma("vm:entry-point", !const bool.fromEnvironment("dart.vm.product"))
+_runExtension(
+    ServiceExtensionHandler handler,
+    String method,
+    List<String> parameterKeys,
+    List<String> parameterValues,
+    SendPort replyPort,
+    Object id,
+    bool trace_service) {
+  var parameters = <String, String>{};
+  for (var i = 0; i < parameterKeys.length; i++) {
+    parameters[parameterKeys[i]] = parameterValues[i];
+  }
+  var response;
+  try {
+    response = handler(method, parameters);
+  } catch (e, st) {
+    var errorDetails = (st == null) ? '$e' : '$e\n$st';
+    response = new ServiceExtensionResponse.error(
+        ServiceExtensionResponse.kExtensionError, errorDetails);
+    _postResponse(replyPort, id, response, trace_service);
+    return;
+  }
+  if (response is! Future) {
+    response = new ServiceExtensionResponse.error(
+        ServiceExtensionResponse.kExtensionError,
+        "Extension handler must return a Future");
+    _postResponse(replyPort, id, response, trace_service);
+    return;
+  }
+  response.catchError((e, st) {
+    // Catch any errors eagerly and wrap them in a ServiceExtensionResponse.
+    var errorDetails = (st == null) ? '$e' : '$e\n$st';
+    return new ServiceExtensionResponse.error(
+        ServiceExtensionResponse.kExtensionError, errorDetails);
+  }).then((response) {
+    // Post the valid response or the wrapped error after verifying that
+    // the response is a ServiceExtensionResponse.
+    if (response is! ServiceExtensionResponse) {
+      response = new ServiceExtensionResponse.error(
+          ServiceExtensionResponse.kExtensionError,
+          "Extension handler must complete to a ServiceExtensionResponse");
+    }
+    _postResponse(replyPort, id, response, trace_service);
+  }).catchError((e, st) {
+    // We do not expect any errors to occur in the .then or .catchError blocks
+    // but, suppress them just in case.
+  });
+}
+
+// This code is only invoked by _runExtension.
+_postResponse(SendPort replyPort, Object id, ServiceExtensionResponse response,
+    bool trace_service) {
+  assert(replyPort != null);
+  if (id == null) {
+    if (trace_service) {
+      print("vm-service: posting no response for request");
+    }
+    // No id -> no response.
+    replyPort.send(null);
+    return;
+  }
+  assert(id != null);
+  StringBuffer sb = new StringBuffer();
+  sb.write('{"jsonrpc":"2.0",');
+  if (response.isError()) {
+    if (trace_service) {
+      print("vm-service: posting error response for request $id");
+    }
+    sb.write('"error":');
+  } else {
+    if (trace_service) {
+      print("vm-service: posting response for request $id");
+    }
+    sb.write('"result":');
+  }
+  sb.write('${response._toString()},');
+  if (id is String) {
+    sb.write('"id":"$id"}');
+  } else {
+    sb.write('"id":$id}');
+  }
+  replyPort.send(sb.toString());
+}
+
+@patch
+int _getServiceMajorVersion() native "Developer_getServiceMajorVersion";
+
+@patch
+int _getServiceMinorVersion() native "Developer_getServiceMinorVersion";
+
+@patch
+void _getServerInfo(SendPort sendPort) native "Developer_getServerInfo";
+
+@patch
+void _webServerControl(SendPort sendPort, bool enable)
+    native "Developer_webServerControl";
+
+@patch
+String _getIsolateIDFromSendPort(SendPort sendPort)
+    native "Developer_getIsolateIDFromSendPort";
diff --git a/sdk_nnbd/lib/_internal/vm/lib/double.dart b/sdk_nnbd/lib/_internal/vm/lib/double.dart
new file mode 100644
index 0000000..01e8d58
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/double.dart
@@ -0,0 +1,365 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+@pragma("vm:entry-point")
+class _Double implements double {
+  @pragma("vm:exact-result-type", _Double)
+  factory _Double.fromInteger(int value) native "Double_doubleFromInteger";
+
+  int get hashCode native "Double_hashCode";
+  int get _identityHashCode native "Double_hashCode";
+
+  @pragma("vm:exact-result-type", _Double)
+  @pragma("vm:never-inline")
+  double operator +(num other) {
+    return _add(other.toDouble());
+  }
+
+  @pragma("vm:exact-result-type", _Double)
+  double _add(double other) native "Double_add";
+
+  @pragma("vm:exact-result-type", _Double)
+  @pragma("vm:never-inline")
+  double operator -(num other) {
+    return _sub(other.toDouble());
+  }
+
+  @pragma("vm:exact-result-type", _Double)
+  double _sub(double other) native "Double_sub";
+
+  @pragma("vm:exact-result-type", _Double)
+  @pragma("vm:never-inline")
+  double operator *(num other) {
+    return _mul(other.toDouble());
+  }
+
+  @pragma("vm:exact-result-type", _Double)
+  double _mul(double other) native "Double_mul";
+
+  int operator ~/(num other) {
+    return _trunc_div(other.toDouble());
+  }
+
+  @pragma("vm:non-nullable-result-type")
+  int _trunc_div(double other) native "Double_trunc_div";
+
+  @pragma("vm:exact-result-type", _Double)
+  @pragma("vm:never-inline")
+  double operator /(num other) {
+    return _div(other.toDouble());
+  }
+
+  @pragma("vm:exact-result-type", _Double)
+  double _div(double other) native "Double_div";
+
+  double operator %(num other) {
+    return _modulo(other.toDouble());
+  }
+
+  @pragma("vm:exact-result-type", _Double)
+  double _modulo(double other) native "Double_modulo";
+
+  double remainder(num other) {
+    return _remainder(other.toDouble());
+  }
+
+  double _remainder(double other) native "Double_remainder";
+
+  @pragma("vm:exact-result-type", _Double)
+  double operator -() native "Double_flipSignBit";
+
+  @pragma("vm:exact-result-type", bool)
+  @pragma("vm:never-inline")
+  bool operator ==(Object other) {
+    return (other is num) && _equal(other.toDouble());
+  }
+
+  @pragma("vm:exact-result-type", bool)
+  bool _equal(double other) native "Double_equal";
+  @pragma("vm:exact-result-type", bool)
+  bool _equalToInteger(int other) native "Double_equalToInteger";
+
+  @pragma("vm:exact-result-type", bool)
+  @pragma("vm:never-inline")
+  bool operator <(num other) {
+    return other > this;
+  }
+
+  @pragma("vm:exact-result-type", bool)
+  @pragma("vm:never-inline")
+  bool operator >(num other) {
+    return _greaterThan(other.toDouble());
+  }
+
+  @pragma("vm:exact-result-type", bool)
+  bool _greaterThan(double other) native "Double_greaterThan";
+
+  @pragma("vm:exact-result-type", bool)
+  @pragma("vm:never-inline")
+  bool operator >=(num other) {
+    return (this == other) || (this > other);
+  }
+
+  @pragma("vm:exact-result-type", bool)
+  @pragma("vm:never-inline")
+  bool operator <=(num other) {
+    return (this == other) || (this < other);
+  }
+
+  double _addFromInteger(int other) {
+    return new _Double.fromInteger(other)._add(this);
+  }
+
+  double _subFromInteger(int other) {
+    return new _Double.fromInteger(other)._sub(this);
+  }
+
+  @pragma("vm:exact-result-type", "dart:core#_Double")
+  double _mulFromInteger(int other) {
+    return new _Double.fromInteger(other)._mul(this);
+  }
+
+  int _truncDivFromInteger(int other) {
+    return new _Double.fromInteger(other)._trunc_div(this);
+  }
+
+  double _moduloFromInteger(int other) {
+    return new _Double.fromInteger(other)._modulo(this);
+  }
+
+  double _remainderFromInteger(int other) {
+    return new _Double.fromInteger(other)._remainder(this);
+  }
+
+  bool _greaterThanFromInteger(int other)
+      native "Double_greaterThanFromInteger";
+
+  @pragma("vm:exact-result-type", bool)
+  bool get isNegative native "Double_getIsNegative";
+  @pragma("vm:exact-result-type", bool)
+  bool get isInfinite native "Double_getIsInfinite";
+  @pragma("vm:exact-result-type", bool)
+  bool get isNaN native "Double_getIsNaN";
+  bool get isFinite => !isInfinite && !isNaN; // Can be optimized.
+
+  double abs() {
+    // Handle negative 0.0.
+    if (this == 0.0) return 0.0;
+    return this < 0.0 ? -this : this;
+  }
+
+  double get sign {
+    if (this > 0.0) return 1.0;
+    if (this < 0.0) return -1.0;
+    return this; // +/-0.0 or NaN.
+  }
+
+  int round() => roundToDouble().toInt();
+  int floor() => floorToDouble().toInt();
+  int ceil() => ceilToDouble().toInt();
+  int truncate() => truncateToDouble().toInt();
+
+  @pragma("vm:exact-result-type", _Double)
+  double roundToDouble() native "Double_round";
+  @pragma("vm:exact-result-type", _Double)
+  double floorToDouble() native "Double_floor";
+  @pragma("vm:exact-result-type", _Double)
+  double ceilToDouble() native "Double_ceil";
+  @pragma("vm:exact-result-type", _Double)
+  double truncateToDouble() native "Double_truncate";
+
+  num clamp(num lowerLimit, num upperLimit) {
+    if (lowerLimit is! num) {
+      throw new ArgumentError.value(lowerLimit, "lowerLimit", "not a number");
+    }
+    if (upperLimit is! num) {
+      throw new ArgumentError.value(upperLimit, "upperLimit", "not a number");
+    }
+
+    if (lowerLimit.compareTo(upperLimit) > 0) {
+      throw new ArgumentError(lowerLimit);
+    }
+    if (lowerLimit.isNaN) return lowerLimit;
+    if (this.compareTo(lowerLimit) < 0) return lowerLimit;
+    if (this.compareTo(upperLimit) > 0) return upperLimit;
+    return this;
+  }
+
+  @pragma("vm:non-nullable-result-type")
+  int toInt() native "Double_toInt";
+
+  double toDouble() {
+    return this;
+  }
+
+  static const int CACHE_SIZE_LOG2 = 3;
+  static const int CACHE_LENGTH = 1 << (CACHE_SIZE_LOG2 + 1);
+  static const int CACHE_MASK = CACHE_LENGTH - 1;
+  // Each key (double) followed by its toString result.
+  static final List _cache = new List(CACHE_LENGTH);
+  static int _cacheEvictIndex = 0;
+
+  String _toString() native "Double_toString";
+
+  String toString() {
+    // TODO(koda): Consider starting at most recently inserted.
+    for (int i = 0; i < CACHE_LENGTH; i += 2) {
+      // Need 'identical' to handle negative zero, etc.
+      if (identical(_cache[i], this)) {
+        return _cache[i + 1];
+      }
+    }
+    // TODO(koda): Consider optimizing all small integral values.
+    if (identical(0.0, this)) {
+      return "0.0";
+    }
+    String result = _toString();
+    // Replace the least recently inserted entry.
+    _cache[_cacheEvictIndex] = this;
+    _cache[_cacheEvictIndex + 1] = result;
+    _cacheEvictIndex = (_cacheEvictIndex + 2) & CACHE_MASK;
+    return result;
+  }
+
+  String toStringAsFixed(int fractionDigits) {
+    // See ECMAScript-262, 15.7.4.5 for details.
+
+    if (fractionDigits is! int) {
+      throw new ArgumentError.value(
+          fractionDigits, "fractionDigits", "not an integer");
+    }
+    // Step 2.
+    if (fractionDigits < 0 || fractionDigits > 20) {
+      throw new RangeError.range(fractionDigits, 0, 20, "fractionDigits");
+    }
+
+    // Step 3.
+    double x = this;
+
+    // Step 4.
+    if (isNaN) return "NaN";
+
+    // Step 5 and 6 skipped. Will be dealt with by native function.
+
+    // Step 7.
+    if (x >= 1e21 || x <= -1e21) {
+      return x.toString();
+    }
+
+    return _toStringAsFixed(fractionDigits);
+  }
+
+  String _toStringAsFixed(int fractionDigits) native "Double_toStringAsFixed";
+
+  String toStringAsExponential([int fractionDigits]) {
+    // See ECMAScript-262, 15.7.4.6 for details.
+
+    // The EcmaScript specification checks for NaN and Infinity before looking
+    // at the fractionDigits. In Dart we are consistent with toStringAsFixed and
+    // look at the fractionDigits first.
+
+    // Step 7.
+    if (fractionDigits != null) {
+      if (fractionDigits is! int) {
+        throw new ArgumentError.value(
+            fractionDigits, "fractionDigits", "not an integer");
+      }
+      if (fractionDigits < 0 || fractionDigits > 20) {
+        throw new RangeError.range(fractionDigits, 0, 20, "fractionDigits");
+      }
+    }
+
+    if (isNaN) return "NaN";
+    if (this == double.infinity) return "Infinity";
+    if (this == -double.infinity) return "-Infinity";
+
+    // The dart function prints the shortest representation when fractionDigits
+    // equals null. The native function wants -1 instead.
+    fractionDigits = (fractionDigits == null) ? -1 : fractionDigits;
+
+    return _toStringAsExponential(fractionDigits);
+  }
+
+  String _toStringAsExponential(int fractionDigits)
+      native "Double_toStringAsExponential";
+
+  String toStringAsPrecision(int precision) {
+    // See ECMAScript-262, 15.7.4.7 for details.
+
+    // The EcmaScript specification checks for NaN and Infinity before looking
+    // at the fractionDigits. In Dart we are consistent with toStringAsFixed and
+    // look at the fractionDigits first.
+
+    if (precision is! int) {
+      throw new ArgumentError.value(precision, "precision", "not an integer");
+    }
+    // Step 8.
+    if (precision < 1 || precision > 21) {
+      throw new RangeError.range(precision, 1, 21, "precision");
+    }
+
+    if (isNaN) return "NaN";
+    if (this == double.infinity) return "Infinity";
+    if (this == -double.infinity) return "-Infinity";
+
+    return _toStringAsPrecision(precision);
+  }
+
+  String _toStringAsPrecision(int fractionDigits)
+      native "Double_toStringAsPrecision";
+
+  // Order is: NaN > Infinity > ... > 0.0 > -0.0 > ... > -Infinity.
+  int compareTo(num other) {
+    const int EQUAL = 0, LESS = -1, GREATER = 1;
+    if (this < other) {
+      return LESS;
+    } else if (this > other) {
+      return GREATER;
+    } else if (this == other) {
+      if (this == 0.0) {
+        bool thisIsNegative = isNegative;
+        bool otherIsNegative = other.isNegative;
+        if (thisIsNegative == otherIsNegative) {
+          return EQUAL;
+        }
+        return thisIsNegative ? LESS : GREATER;
+      } else if (other is int) {
+        // Compare as integers as it is more precise if the integer value is
+        // outside of MIN_EXACT_INT_TO_DOUBLE..MAX_EXACT_INT_TO_DOUBLE range.
+        const int MAX_EXACT_INT_TO_DOUBLE = 9007199254740992; // 2^53.
+        const int MIN_EXACT_INT_TO_DOUBLE = -MAX_EXACT_INT_TO_DOUBLE;
+        if ((MIN_EXACT_INT_TO_DOUBLE <= other) &&
+            (other <= MAX_EXACT_INT_TO_DOUBLE)) {
+          return EQUAL;
+        }
+        const bool limitIntsTo64Bits = ((1 << 64) == 0);
+        if (limitIntsTo64Bits) {
+          // With integers limited to 64 bits, double.toInt() clamps
+          // double value to fit into the MIN_INT64..MAX_INT64 range.
+          // MAX_INT64 is not precisely representable as double, so
+          // integers near MAX_INT64 compare as equal to (MAX_INT64 + 1) when
+          // represented as doubles.
+          // There is no similar problem with MIN_INT64 as it is precisely
+          // representable as double.
+          const double maxInt64Plus1AsDouble = 9223372036854775808.0;
+          if (this >= maxInt64Plus1AsDouble) {
+            return GREATER;
+          }
+        }
+        return toInt().compareTo(other);
+      } else {
+        return EQUAL;
+      }
+    } else if (isNaN) {
+      return other.isNaN ? EQUAL : GREATER;
+    } else {
+      // Other is NaN.
+      return LESS;
+    }
+  }
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/double_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/double_patch.dart
new file mode 100644
index 0000000..bad7834
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/double_patch.dart
@@ -0,0 +1,120 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+// VM implementation of double.
+
+@patch
+class double {
+  static double _nativeParse(String str, int start, int end)
+      native "Double_parse";
+
+  static double _tryParseDouble(var str, var start, var end) {
+    assert(start < end);
+    const int _DOT = 0x2e; // '.'
+    const int _ZERO = 0x30; // '0'
+    const int _MINUS = 0x2d; // '-'
+    const int _N = 0x4e; // 'N'
+    const int _a = 0x61; // 'a'
+    const int _I = 0x49; // 'I'
+    const int _e = 0x65; // 'e'
+    int exponent = 0;
+    // Set to non-zero if a digit is seen. Avoids accepting ".".
+    bool digitsSeen = false;
+    // Added to exponent for each digit. Set to -1 when seeing '.'.
+    int exponentDelta = 0;
+    double doubleValue = 0.0;
+    double sign = 1.0;
+    int firstChar = str.codeUnitAt(start);
+    if (firstChar == _MINUS) {
+      sign = -1.0;
+      start++;
+      if (start == end) return null;
+      firstChar = str.codeUnitAt(start);
+    }
+    if (firstChar == _I) {
+      if (end == start + 8 && str.startsWith("nfinity", start + 1)) {
+        return sign * double.infinity;
+      }
+      return null;
+    }
+    if (firstChar == _N) {
+      if (end == start + 3 &&
+          str.codeUnitAt(start + 1) == _a &&
+          str.codeUnitAt(start + 2) == _N) {
+        return double.nan;
+      }
+      return null;
+    }
+
+    int firstDigit = firstChar ^ _ZERO;
+    if (firstDigit <= 9) {
+      start++;
+      doubleValue = firstDigit.toDouble();
+      digitsSeen = true;
+    }
+    for (int i = start; i < end; i++) {
+      int c = str.codeUnitAt(i);
+      int digit = c ^ _ZERO; // '0'-'9' characters are now 0-9 integers.
+      if (digit <= 9) {
+        doubleValue = 10.0 * doubleValue + digit;
+        // Doubles at or above this value (2**53) might have lost precission.
+        const double MAX_EXACT_DOUBLE = 9007199254740992.0;
+        if (doubleValue >= MAX_EXACT_DOUBLE) return null;
+        exponent += exponentDelta;
+        digitsSeen = true;
+      } else if (c == _DOT && exponentDelta == 0) {
+        exponentDelta = -1;
+      } else if ((c | 0x20) == _e) {
+        i++;
+        if (i == end) return null;
+        // int._tryParseSmi treats its end argument as inclusive.
+        int expPart = int._tryParseSmi(str, i, end - 1);
+        if (expPart == null) return null;
+        exponent += expPart;
+        break;
+      } else {
+        return null;
+      }
+    }
+    if (!digitsSeen) return null; // No digits.
+    if (exponent == 0) return sign * doubleValue;
+    const P10 = POWERS_OF_TEN; // From shared library
+    if (exponent < 0) {
+      int negExponent = -exponent;
+      if (negExponent >= P10.length) return null;
+      return sign * (doubleValue / P10[negExponent]);
+    }
+    if (exponent >= P10.length) return null;
+    return sign * (doubleValue * P10[exponent]);
+  }
+
+  static double _parse(var str) {
+    int len = str.length;
+    int start = str._firstNonWhitespace();
+    if (start == len) return null; // All whitespace.
+    int end = str._lastNonWhitespace() + 1;
+    assert(start < end);
+    var result = _tryParseDouble(str, start, end);
+    if (result != null) return result;
+    return _nativeParse(str, start, end);
+  }
+
+  @patch
+  static double parse(String source,
+      [@deprecated double onError(String source)]) {
+    var result = _parse(source);
+    if (result == null) {
+      if (onError == null) throw new FormatException("Invalid double", source);
+      return onError(source);
+    }
+    return result;
+  }
+
+  @patch
+  static double tryParse(String source) => _parse(source);
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/empty_source.dart b/sdk_nnbd/lib/_internal/vm/lib/empty_source.dart
new file mode 100644
index 0000000..1521417
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/empty_source.dart
@@ -0,0 +1,7 @@
+// 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.
+
+// @dart = 2.5
+
+// THIS FILE INTENTIONALLY LEFT BLANK.
diff --git a/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart
new file mode 100644
index 0000000..628419c
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/errors_patch.dart
@@ -0,0 +1,592 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+@patch
+class Error {
+  @patch
+  static String _objectToString(Object object) {
+    return Object._toString(object);
+  }
+
+  @patch
+  static String _stringToSafeString(String string) {
+    return json.encode(string);
+  }
+
+  @patch
+  StackTrace get stackTrace => _stackTrace;
+
+  @pragma("vm:entry-point")
+  StackTrace _stackTrace;
+}
+
+class _AssertionError extends Error implements AssertionError {
+  @pragma("vm:entry-point")
+  _AssertionError._create(
+      this._failedAssertion, this._url, this._line, this._column, this.message);
+
+  // AssertionError_throwNew in errors.cc fishes the assertion source code
+  // out of the script. It expects a Dart stack frame from class
+  // _AssertionError. Thus we need a Dart stub that calls the native code.
+  @pragma("vm:entry-point", "call")
+  static _throwNew(int assertionStart, int assertionEnd, Object message) {
+    _doThrowNew(assertionStart, assertionEnd, message);
+  }
+
+  static _doThrowNew(int assertionStart, int assertionEnd, Object message)
+      native "AssertionError_throwNew";
+
+  @pragma("vm:entry-point", "call")
+  static _evaluateAssertion(condition) {
+    if (identical(condition, true) || identical(condition, false)) {
+      return condition;
+    }
+    if (condition is _Closure) {
+      return (condition as dynamic)();
+    }
+    if (condition is Function) {
+      condition = condition();
+    }
+    return condition;
+  }
+
+  String get _messageString {
+    if (message == null) return "is not true.";
+    if (message is String) return message;
+    return Error.safeToString(message);
+  }
+
+  String toString() {
+    if (_url == null) {
+      if (message == null) return _failedAssertion?.trim();
+      return "'${_failedAssertion?.trim()}': $_messageString";
+    }
+    var columnInfo = "";
+    if (_column > 0) {
+      // Only add column information if it is valid.
+      columnInfo = " pos $_column";
+    }
+    return "'$_url': Failed assertion: line $_line$columnInfo: "
+        "'$_failedAssertion': $_messageString";
+  }
+
+  final String _failedAssertion;
+  final String _url;
+  final int _line;
+  final int _column;
+  final Object message;
+}
+
+class _TypeError extends _AssertionError implements TypeError {
+  @pragma("vm:entry-point")
+  _TypeError._create(String url, int line, int column, String errorMsg)
+      : super._create("is assignable", url, line, column, errorMsg);
+
+  static _throwNew(int location, Object src_value, _Type dst_type,
+      String dst_name) native "TypeError_throwNew";
+
+  String toString() => super.message;
+}
+
+class _CastError extends Error implements CastError {
+  @pragma("vm:entry-point")
+  _CastError._create(this._url, this._line, this._column, this._errorMsg);
+
+  // A CastError is allocated by TypeError._throwNew() when dst_name equals
+  // Symbols::InTypeCast().
+
+  String toString() => _errorMsg;
+
+  // Fields _url, _line, and _column are only used for debugging purposes.
+  final String _url;
+  final int _line;
+  final int _column;
+  final String _errorMsg;
+}
+
+@patch
+class FallThroughError {
+  @patch
+  @pragma("vm:entry-point")
+  FallThroughError._create(String url, int line)
+      : _url = url,
+        _line = line;
+
+  static _throwNew(int case_clause_pos) native "FallThroughError_throwNew";
+
+  @patch
+  String toString() {
+    return "'$_url': Switch case fall-through at line $_line.";
+  }
+
+  // These new fields cannot be declared final, because a constructor exists
+  // in the original version of this patched class.
+  String _url;
+  int _line;
+}
+
+class _InternalError {
+  @pragma("vm:entry-point")
+  const _InternalError(this._msg);
+  String toString() => "InternalError: '${_msg}'";
+  final String _msg;
+}
+
+@patch
+@pragma("vm:entry-point")
+class UnsupportedError {
+  static _throwNew(String msg) {
+    throw new UnsupportedError(msg);
+  }
+}
+
+@patch
+class CyclicInitializationError {
+  static _throwNew(String variableName) {
+    throw new CyclicInitializationError(variableName);
+  }
+}
+
+@patch
+class AbstractClassInstantiationError {
+  @pragma("vm:entry-point")
+  AbstractClassInstantiationError._create(
+      this._className, this._url, this._line);
+
+  static _throwNew(int case_clause_pos, String className)
+      native "AbstractClassInstantiationError_throwNew";
+
+  @patch
+  String toString() {
+    return "Cannot instantiate abstract class $_className: "
+        "_url '$_url' line $_line";
+  }
+
+  // These new fields cannot be declared final, because a constructor exists
+  // in the original version of this patched class.
+  String _url;
+  int _line;
+}
+
+@patch
+class NoSuchMethodError {
+  // Deprecated members to be removed.
+  Symbol _memberName;
+  List _arguments;
+  Map<Symbol, dynamic> _namedArguments;
+  List _existingArgumentNames;
+
+  final Object _receiver;
+  final _InvocationMirror _invocation;
+
+  @patch
+  NoSuchMethodError.withInvocation(Object receiver, Invocation invocation)
+      : _receiver = receiver,
+        _invocation = invocation as _InvocationMirror;
+
+  static void _throwNewInvocation(Object receiver, Invocation invocation) {
+    throw new NoSuchMethodError.withInvocation(receiver, invocation);
+  }
+
+  // The compiler emits a call to _throwNew when it cannot resolve a static
+  // method at compile time. The receiver is actually the literal class of the
+  // unresolved method.
+  @pragma("vm:entry-point", "call")
+  static void _throwNew(Object receiver, String memberName, int invocation_type,
+      Object typeArguments, List arguments, List argumentNames) {
+    throw new NoSuchMethodError._withType(receiver, memberName, invocation_type,
+        typeArguments, arguments, argumentNames);
+  }
+
+  static void _throwNewIfNotLoaded(
+      _LibraryPrefix prefix,
+      Object receiver,
+      String memberName,
+      int invocation_type,
+      Object typeArguments,
+      List arguments,
+      List argumentNames) {
+    if (!prefix.isLoaded()) {
+      _throwNew(receiver, memberName, invocation_type, typeArguments, arguments,
+          argumentNames);
+    }
+  }
+
+  // TODO(regis): Deprecated member still used by dart2js to be removed.
+  // Remember the type from the invocation mirror or static compilation
+  // analysis when thrown directly with _throwNew. A negative value means
+  // that no information is available.
+  int _invocation_type;
+
+  // TODO(regis): Deprecated constructor still used by dart2js to be removed.
+  @patch
+  NoSuchMethodError(Object receiver, Symbol memberName,
+      List positionalArguments, Map<Symbol, dynamic> namedArguments,
+      [List existingArgumentNames = null])
+      : _receiver = receiver,
+        _invocation = null,
+        _memberName = memberName,
+        _arguments = positionalArguments,
+        _namedArguments = namedArguments,
+        _existingArgumentNames = existingArgumentNames,
+        _invocation_type = -1;
+
+  // Helper to build a map of named arguments.
+  static Map<Symbol, dynamic> _NamedArgumentsMap(
+      List arguments, List argumentNames) {
+    Map<Symbol, dynamic> namedArguments = new Map<Symbol, dynamic>();
+    int numPositionalArguments = arguments.length - argumentNames.length;
+    for (int i = 0; i < argumentNames.length; i++) {
+      var arg_value = arguments[numPositionalArguments + i];
+      namedArguments[new Symbol(argumentNames[i])] = arg_value;
+    }
+    return namedArguments;
+  }
+
+  // Constructor called from Exceptions::ThrowByType(kNoSuchMethod) and from
+  // _throwNew above, taking a TypeArguments object rather than an unpacked list
+  // of types, as well as a list of all arguments and a list of names, rather
+  // than a separate list of positional arguments and a map of named arguments.
+  @pragma("vm:entry-point")
+  NoSuchMethodError._withType(
+      this._receiver,
+      String memberName,
+      int invocation_type,
+      Object typeArguments,
+      List arguments,
+      List argumentNames)
+      : this._invocation = new _InvocationMirror._withType(
+            new Symbol(memberName),
+            invocation_type,
+            typeArguments != null
+                // TODO(33073): Use actual count of type arguments in place of 0.
+                ? _InvocationMirror._unpackTypeArguments(typeArguments, 0)
+                : null,
+            argumentNames != null
+                ? arguments.sublist(0, arguments.length - argumentNames.length)
+                : arguments,
+            argumentNames != null
+                ? _NamedArgumentsMap(arguments, argumentNames)
+                : null);
+
+  static String _existingMethodSignature(Object receiver, String methodName,
+      int invocationType) native "NoSuchMethodError_existingMethodSignature";
+
+  @patch
+  String toString() {
+    // TODO(regis): Remove this null check once dart2js is updated.
+    if (_invocation == null) {
+      // Use deprecated version of toString.
+      return _toStringDeprecated();
+    }
+    String memberName =
+        internal.Symbol.computeUnmangledName(_invocation.memberName);
+    var level = (_invocation._type >> _InvocationMirror._LEVEL_SHIFT) &
+        _InvocationMirror._LEVEL_MASK;
+    var kind = _invocation._type & _InvocationMirror._KIND_MASK;
+    if (kind == _InvocationMirror._LOCAL_VAR) {
+      return "NoSuchMethodError: Cannot assign to final variable '$memberName'";
+    }
+
+    StringBuffer typeArgumentsBuf = null;
+    var typeArguments = _invocation.typeArguments;
+    if ((typeArguments != null) && (typeArguments.length > 0)) {
+      typeArgumentsBuf = new StringBuffer();
+      typeArgumentsBuf.write("<");
+      for (int i = 0; i < typeArguments.length; i++) {
+        if (i > 0) {
+          typeArgumentsBuf.write(", ");
+        }
+        typeArgumentsBuf.write(Error.safeToString(typeArguments[i]));
+      }
+      typeArgumentsBuf.write(">");
+    }
+    StringBuffer argumentsBuf = new StringBuffer();
+    var positionalArguments = _invocation.positionalArguments;
+    int argumentCount = 0;
+    if (positionalArguments != null) {
+      for (; argumentCount < positionalArguments.length; argumentCount++) {
+        if (argumentCount > 0) {
+          argumentsBuf.write(", ");
+        }
+        argumentsBuf
+            .write(Error.safeToString(positionalArguments[argumentCount]));
+      }
+    }
+    var namedArguments = _invocation.namedArguments;
+    if (namedArguments != null) {
+      namedArguments.forEach((Symbol key, var value) {
+        if (argumentCount > 0) {
+          argumentsBuf.write(", ");
+        }
+        argumentsBuf.write(internal.Symbol.computeUnmangledName(key));
+        argumentsBuf.write(": ");
+        argumentsBuf.write(Error.safeToString(value));
+        argumentCount++;
+      });
+    }
+    String existingSig =
+        _existingMethodSignature(_receiver, memberName, _invocation._type);
+    String argsMsg = existingSig != null ? " with matching arguments" : "";
+
+    String kindBuf;
+    if (kind >= 0 && kind < 5) {
+      kindBuf = (const [
+        "method",
+        "getter",
+        "setter",
+        "getter or setter",
+        "variable"
+      ])[kind];
+    }
+
+    StringBuffer msgBuf = new StringBuffer("NoSuchMethodError: ");
+    bool is_type_call = false;
+    switch (level) {
+      case _InvocationMirror._DYNAMIC:
+        {
+          if (_receiver == null) {
+            if (existingSig != null) {
+              msgBuf.writeln("The null object does not have a $kindBuf "
+                  "'$memberName'$argsMsg.");
+            } else {
+              msgBuf.writeln("The $kindBuf '$memberName' was called on null.");
+            }
+          } else {
+            if (_receiver is _Closure) {
+              msgBuf.writeln("Closure call with mismatched arguments: "
+                  "function '$memberName'");
+            } else if (_receiver is _Type && memberName == "call") {
+              is_type_call = true;
+              String name = _receiver.toString();
+              msgBuf.writeln("Attempted to use type '$name' as a function. "
+                  "Since types do not define a method 'call', this is not "
+                  "possible. Did you intend to call the $name constructor and "
+                  "forget the 'new' operator?");
+            } else {
+              msgBuf.writeln("Class '${_receiver.runtimeType}' has no instance "
+                  "$kindBuf '$memberName'$argsMsg.");
+            }
+          }
+          break;
+        }
+      case _InvocationMirror._SUPER:
+        {
+          msgBuf.writeln("Super class of class '${_receiver.runtimeType}' has "
+              "no instance $kindBuf '$memberName'$argsMsg.");
+          memberName = "super.$memberName";
+          break;
+        }
+      case _InvocationMirror._STATIC:
+        {
+          msgBuf.writeln("No static $kindBuf '$memberName'$argsMsg "
+              "declared in class '$_receiver'.");
+          break;
+        }
+      case _InvocationMirror._CONSTRUCTOR:
+        {
+          msgBuf.writeln("No constructor '$memberName'$argsMsg declared "
+              "in class '$_receiver'.");
+          memberName = "new $memberName";
+          break;
+        }
+      case _InvocationMirror._TOP_LEVEL:
+        {
+          msgBuf.writeln("No top-level $kindBuf '$memberName'$argsMsg "
+              "declared.");
+          break;
+        }
+    }
+
+    if (level == _InvocationMirror._TOP_LEVEL) {
+      msgBuf.writeln("Receiver: top-level");
+    } else {
+      msgBuf.writeln("Receiver: ${Error.safeToString(_receiver)}");
+    }
+
+    if (kind == _InvocationMirror._METHOD) {
+      String m = is_type_call ? "$_receiver" : "$memberName";
+      msgBuf.write("Tried calling: $m");
+      if (typeArgumentsBuf != null) {
+        msgBuf.write(typeArgumentsBuf);
+      }
+      msgBuf.write("($argumentsBuf)");
+    } else if (argumentCount == 0) {
+      msgBuf.write("Tried calling: $memberName");
+    } else if (kind == _InvocationMirror._SETTER) {
+      msgBuf.write("Tried calling: $memberName$argumentsBuf");
+    } else {
+      msgBuf.write("Tried calling: $memberName = $argumentsBuf");
+    }
+
+    if (existingSig != null) {
+      msgBuf.write("\nFound: $memberName$existingSig");
+    }
+
+    return msgBuf.toString();
+  }
+
+  // TODO(regis): Remove this function once dart2js is updated.
+  String _toStringDeprecated() {
+    var level = (_invocation_type >> _InvocationMirror._LEVEL_SHIFT) &
+        _InvocationMirror._LEVEL_MASK;
+    var type = _invocation_type & _InvocationMirror._KIND_MASK;
+    String memberName = (_memberName == null)
+        ? ""
+        : internal.Symbol.computeUnmangledName(_memberName);
+
+    if (type == _InvocationMirror._LOCAL_VAR) {
+      return "NoSuchMethodError: Cannot assign to final variable '$memberName'";
+    }
+
+    StringBuffer arguments = new StringBuffer();
+    int argumentCount = 0;
+    if (_arguments != null) {
+      for (; argumentCount < _arguments.length; argumentCount++) {
+        if (argumentCount > 0) {
+          arguments.write(", ");
+        }
+        arguments.write(Error.safeToString(_arguments[argumentCount]));
+      }
+    }
+    if (_namedArguments != null) {
+      _namedArguments.forEach((Symbol key, var value) {
+        if (argumentCount > 0) {
+          arguments.write(", ");
+        }
+        arguments.write(internal.Symbol.computeUnmangledName(key));
+        arguments.write(": ");
+        arguments.write(Error.safeToString(value));
+        argumentCount++;
+      });
+    }
+    bool args_mismatch = _existingArgumentNames != null;
+    String args_message = args_mismatch ? " with matching arguments" : "";
+
+    String type_str;
+    if (type >= 0 && type < 5) {
+      type_str = (const [
+        "method",
+        "getter",
+        "setter",
+        "getter or setter",
+        "variable"
+      ])[type];
+    }
+
+    StringBuffer msg_buf = new StringBuffer("NoSuchMethodError: ");
+    bool is_type_call = false;
+    switch (level) {
+      case _InvocationMirror._DYNAMIC:
+        {
+          if (_receiver == null) {
+            if (args_mismatch) {
+              msg_buf.writeln("The null object does not have a $type_str "
+                  "'$memberName'$args_message.");
+            } else {
+              msg_buf
+                  .writeln("The $type_str '$memberName' was called on null.");
+            }
+          } else {
+            if (_receiver is _Closure) {
+              msg_buf.writeln("Closure call with mismatched arguments: "
+                  "function '$memberName'");
+            } else if (_receiver is _Type && memberName == "call") {
+              is_type_call = true;
+              String name = _receiver.toString();
+              msg_buf.writeln("Attempted to use type '$name' as a function. "
+                  "Since types do not define a method 'call', this is not "
+                  "possible. Did you intend to call the $name constructor and "
+                  "forget the 'new' operator?");
+            } else {
+              msg_buf
+                  .writeln("Class '${_receiver.runtimeType}' has no instance "
+                      "$type_str '$memberName'$args_message.");
+            }
+          }
+          break;
+        }
+      case _InvocationMirror._SUPER:
+        {
+          msg_buf.writeln("Super class of class '${_receiver.runtimeType}' has "
+              "no instance $type_str '$memberName'$args_message.");
+          memberName = "super.$memberName";
+          break;
+        }
+      case _InvocationMirror._STATIC:
+        {
+          msg_buf.writeln("No static $type_str '$memberName'$args_message "
+              "declared in class '$_receiver'.");
+          break;
+        }
+      case _InvocationMirror._CONSTRUCTOR:
+        {
+          msg_buf.writeln("No constructor '$memberName'$args_message declared "
+              "in class '$_receiver'.");
+          memberName = "new $memberName";
+          break;
+        }
+      case _InvocationMirror._TOP_LEVEL:
+        {
+          msg_buf.writeln("No top-level $type_str '$memberName'$args_message "
+              "declared.");
+          break;
+        }
+    }
+
+    if (level == _InvocationMirror._TOP_LEVEL) {
+      msg_buf.writeln("Receiver: top-level");
+    } else {
+      msg_buf.writeln("Receiver: ${Error.safeToString(_receiver)}");
+    }
+
+    if (type == _InvocationMirror._METHOD) {
+      String m = is_type_call ? "$_receiver" : "$memberName";
+      msg_buf.write("Tried calling: $m($arguments)");
+    } else if (argumentCount == 0) {
+      msg_buf.write("Tried calling: $memberName");
+    } else if (type == _InvocationMirror._SETTER) {
+      msg_buf.write("Tried calling: $memberName$arguments");
+    } else {
+      msg_buf.write("Tried calling: $memberName = $arguments");
+    }
+
+    if (args_mismatch) {
+      StringBuffer formalParameters = new StringBuffer();
+      for (int i = 0; i < _existingArgumentNames.length; i++) {
+        if (i > 0) {
+          formalParameters.write(", ");
+        }
+        formalParameters.write(_existingArgumentNames[i]);
+      }
+      msg_buf.write("\nFound: $memberName($formalParameters)");
+    }
+
+    return msg_buf.toString();
+  }
+}
+
+@pragma("vm:entry-point")
+class _CompileTimeError extends Error {
+  final String _errorMsg;
+  _CompileTimeError(this._errorMsg);
+  String toString() => _errorMsg;
+}
+
+/// Used by Fasta to report a runtime error when a final field with an
+/// initializer is also initialized in a generative constructor.
+///
+/// Note: in strong mode, this is a compile-time error and this class becomes
+/// obsolete.
+class _DuplicatedFieldInitializerError extends Error {
+  final String _name;
+
+  _DuplicatedFieldInitializerError(this._name);
+
+  toString() => "Error: field '$_name' is already initialized.";
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/expando_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/expando_patch.dart
new file mode 100644
index 0000000..3601908
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/expando_patch.dart
@@ -0,0 +1,153 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+@patch
+class Expando<T> {
+  @patch
+  Expando([String name])
+      : name = name,
+        _data = new List(_minSize),
+        _used = 0;
+
+  static const _minSize = 8;
+  static final _deletedEntry = new _WeakProperty(null, null);
+
+  @patch
+  T operator [](Object object) {
+    _checkType(object);
+
+    var mask = _size - 1;
+    var idx = object._identityHashCode & mask;
+    var wp = _data[idx];
+
+    while (wp != null) {
+      if (identical(wp.key, object)) {
+        return wp.value;
+      } else if (wp.key == null) {
+        // This entry has been cleared by the GC.
+        _data[idx] = _deletedEntry;
+      }
+      idx = (idx + 1) & mask;
+      wp = _data[idx];
+    }
+
+    return null;
+  }
+
+  @patch
+  void operator []=(Object object, T value) {
+    _checkType(object);
+
+    var mask = _size - 1;
+    var idx = object._identityHashCode & mask;
+    var empty_idx = -1;
+    var wp = _data[idx];
+
+    while (wp != null) {
+      if (identical(wp.key, object)) {
+        if (value != null) {
+          // Update the associated value.
+          wp.value = value;
+        } else {
+          // Mark the entry as deleted.
+          _data[idx] = _deletedEntry;
+        }
+        return;
+      } else if ((empty_idx < 0) && identical(wp, _deletedEntry)) {
+        empty_idx = idx; // Insert at this location if not found.
+      } else if (wp.key == null) {
+        // This entry has been cleared by the GC.
+        _data[idx] = _deletedEntry;
+        if (empty_idx < 0) {
+          empty_idx = idx; // Insert at this location if not found.
+        }
+      }
+      idx = (idx + 1) & mask;
+      wp = _data[idx];
+    }
+
+    if (value == null) {
+      // Not entering a null value. We just needed to make sure to clear an
+      // existing value if it existed.
+      return;
+    }
+
+    if (empty_idx >= 0) {
+      // We will be reusing the empty slot below.
+      _used--;
+      idx = empty_idx;
+    }
+
+    if (_used < _limit) {
+      _data[idx] = new _WeakProperty(object, value);
+      _used++;
+      return;
+    }
+
+    // Grow/reallocate if too many slots have been used.
+    _rehash();
+    this[object] = value; // Recursively add the value.
+  }
+
+  _rehash() {
+    // Determine the population count of the map to allocate an appropriately
+    // sized map below.
+    var count = 0;
+    var old_data = _data;
+    var len = old_data.length;
+    for (var i = 0; i < len; i++) {
+      var entry = old_data[i];
+      if ((entry != null) && (entry.key != null)) {
+        // Only count non-cleared entries.
+        count++;
+      }
+    }
+
+    var new_size = _size;
+    if (count <= (new_size >> 2)) {
+      new_size = new_size >> 1;
+    } else if (count > (new_size >> 1)) {
+      new_size = new_size << 1;
+    }
+    new_size = (new_size < _minSize) ? _minSize : new_size;
+
+    // Reset the mappings to empty so that we can just add the existing
+    // valid entries.
+    _data = new List(new_size);
+    _used = 0;
+
+    for (var i = 0; i < old_data.length; i++) {
+      var entry = old_data[i];
+      if (entry != null) {
+        // Ensure that the entry.key is not cleared between checking for it and
+        // inserting it into the new table.
+        var val = entry.value;
+        var key = entry.key;
+        if (key != null) {
+          this[key] = val;
+        }
+      }
+    }
+  }
+
+  static _checkType(object) {
+    if ((object == null) ||
+        (object is bool) ||
+        (object is num) ||
+        (object is String)) {
+      throw new ArgumentError.value(object,
+          "Expandos are not allowed on strings, numbers, booleans or null");
+    }
+  }
+
+  get _size => _data.length;
+  get _limit => (3 * (_size ~/ 4));
+
+  List _data;
+  int _used; // Number of used (active and deleted) slots.
+}
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
new file mode 100644
index 0000000..581582f
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart
@@ -0,0 +1,60 @@
+// 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
+
+// All imports must be in all FFI patch files to not depend on the order
+// the patches are applied.
+import "dart:_internal" show patch;
+import 'dart:typed_data' show TypedData;
+
+DynamicLibrary _open(String name) native "Ffi_dl_open";
+DynamicLibrary _processLibrary() native "Ffi_dl_processLibrary";
+DynamicLibrary _executableLibrary() native "Ffi_dl_executableLibrary";
+
+@patch
+@pragma("vm:entry-point")
+class DynamicLibrary {
+  @patch
+  factory DynamicLibrary.open(String name) {
+    return _open(name);
+  }
+
+  @patch
+  factory DynamicLibrary.process() => _processLibrary();
+
+  @patch
+  factory DynamicLibrary.executable() => _executableLibrary();
+
+  @patch
+  Pointer<T> lookup<T extends NativeType>(String symbolName)
+      native "Ffi_dl_lookup";
+
+  // The real implementation of this function lives in FfiUseSiteTransformer
+  // for interface calls. Only dynamic calls (which are illegal) reach this
+  // implementation.
+  @patch
+  F lookupFunction<T extends Function, F extends Function>(String symbolName) {
+    throw UnsupportedError(
+        "Dynamic invocation of lookupFunction is not supported.");
+  }
+
+  // TODO(dacoharkes): Expose this to users, or extend Pointer?
+  // https://github.com/dart-lang/sdk/issues/35881
+  int getHandle() native "Ffi_dl_getHandle";
+
+  @patch
+  bool operator ==(other) {
+    if (other == null) return false;
+    return getHandle() == other.getHandle();
+  }
+
+  @patch
+  int get hashCode {
+    return getHandle().hashCode;
+  }
+
+  @patch
+  Pointer<Void> get handle => Pointer.fromAddress(getHandle());
+}
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
new file mode 100644
index 0000000..876184d
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/ffi_native_type_patch.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.
+
+// @dart = 2.5
+
+// All imports must be in all FFI patch files to not depend on the order
+// the patches are applied.
+import "dart:_internal" show patch;
+import 'dart:typed_data' show TypedData;
+
+// NativeType is not private, because it is used in type arguments.
+// NativeType is abstract because it not used with const constructors in
+// annotations directly, so it should never be instantiated at runtime.
+@patch
+@pragma("vm:entry-point")
+abstract class NativeType {}
+
+@patch
+@pragma("vm:entry-point")
+class _NativeInteger extends NativeType {}
+
+@patch
+@pragma("vm:entry-point")
+class _NativeDouble extends NativeType {}
+
+@patch
+@pragma("vm:entry-point")
+class Int8 extends _NativeInteger {}
+
+@patch
+@pragma("vm:entry-point")
+class Int16 extends _NativeInteger {}
+
+@patch
+@pragma("vm:entry-point")
+class Int32 extends _NativeInteger {}
+
+@patch
+@pragma("vm:entry-point")
+class Int64 extends _NativeInteger {}
+
+@patch
+@pragma("vm:entry-point")
+class Uint8 extends _NativeInteger {}
+
+@patch
+@pragma("vm:entry-point")
+class Uint16 extends _NativeInteger {}
+
+@patch
+@pragma("vm:entry-point")
+class Uint32 extends _NativeInteger {}
+
+@patch
+@pragma("vm:entry-point")
+class Uint64 extends _NativeInteger {}
+
+@patch
+@pragma("vm:entry-point")
+class IntPtr extends _NativeInteger {}
+
+@patch
+@pragma("vm:entry-point")
+class Float extends _NativeDouble {}
+
+@patch
+@pragma("vm:entry-point")
+class Double extends _NativeDouble {}
+
+@patch
+@pragma("vm:entry-point")
+abstract class Void extends NativeType {}
+
+@patch
+@pragma("vm:entry-point")
+abstract class NativeFunction<T extends Function> extends NativeType {}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/ffi_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/ffi_patch.dart
new file mode 100644
index 0000000..25c3f41
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/ffi_patch.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.
+
+// @dart = 2.5
+
+// All imports must be in all FFI patch files to not depend on the order
+// the patches are applied.
+import "dart:_internal" show patch;
+import 'dart:typed_data' show TypedData;
+
+@patch
+int sizeOf<T extends NativeType>() native "Ffi_sizeOf";
+
+Pointer<T> _allocate<T extends NativeType>(int count) native "Ffi_allocate";
+
+Pointer<T> _fromAddress<T extends NativeType>(int ptr) native "Ffi_fromAddress";
+
+// The real implementation of this function (for interface calls) lives in
+// BuildFfiAsFunctionCall in the Kernel frontend. No calls can actually reach
+// this function.
+DS _asFunctionInternal<DS extends Function, NS extends Function>(
+    Pointer<NativeFunction<NS>> ptr) native "Ffi_asFunctionInternal";
+
+dynamic _asExternalTypedData(Pointer ptr, int count)
+    native "Ffi_asExternalTypedData";
+
+@patch
+@pragma("vm:entry-point")
+class Pointer<T extends NativeType> {
+  @patch
+  factory Pointer.allocate({int count: 1}) => _allocate<T>(count);
+
+  @patch
+  factory Pointer.fromAddress(int ptr) => _fromAddress(ptr);
+
+  @patch
+  static Pointer<NativeFunction<T>> fromFunction<T extends Function>(
+      @DartRepresentationOf("T") Function f,
+      Object exceptionalReturn) native "Ffi_fromFunction";
+
+  // TODO(sjindel): When NNBD is available, we should change `value` to be
+  // non-null.
+  @patch
+  void store(Object value) native "Ffi_store";
+
+  @patch
+  R load<R>() native "Ffi_load";
+
+  @patch
+  int get address native "Ffi_address";
+
+  // Note this could also be implmented without an extra native as offsetBy
+  // (elementSize()*index). This would be 2 native calls rather than one. What
+  // would be better?
+  @patch
+  Pointer<T> elementAt(int index) native "Ffi_elementAt";
+
+  // Note this could also be implmented without an extra  native as
+  // fromAddress(address). This would be 2 native calls rather than one.
+  // What would be better?
+  @patch
+  Pointer<T> offsetBy(int offsetInBytes) native "Ffi_offsetBy";
+
+  // Note this could also be implemented without an extra native as
+  // fromAddress(address). This would be 2 native calls rather than one.
+  // What would be better?
+  @patch
+  Pointer<U> cast<U extends NativeType>() native "Ffi_cast";
+
+  @patch
+  R asFunction<R extends Function>() {
+    throw UnsupportedError("Pointer.asFunction cannot be called dynamically.");
+  }
+
+  @patch
+  void free() native "Ffi_free";
+
+  @patch
+  TypedData asExternalTypedData({int count: 1}) =>
+      _asExternalTypedData(this, count);
+}
+
+// Returns the ABI used for size and alignment calculations.
+// See pkg/vm/lib/transformations/ffi.dart.
+@pragma('vm:prefer-inline')
+int _abi()
+    native "Recognized method: method is directly interpreted by the bytecode interpreter or IR graph is built in the flow graph builder.";
diff --git a/sdk_nnbd/lib/_internal/vm/lib/function.dart b/sdk_nnbd/lib/_internal/vm/lib/function.dart
new file mode 100644
index 0000000..b055327
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/function.dart
@@ -0,0 +1,56 @@
+// 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 "core_patch.dart";
+
+@pragma("vm:entry-point")
+class _Closure implements Function {
+  factory _Closure._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  bool operator ==(Object other) native "Closure_equals";
+
+  int get hashCode {
+    _hash ??= _computeHash();
+    return _hash;
+  }
+
+  _Closure get call => this;
+
+  _Closure _clone() native "Closure_clone";
+
+  int _computeHash() native "Closure_computeHash";
+
+  // No instance fields should be declared before the following fields whose
+  // offsets must be identical in Dart and C++.
+
+  // The following fields are declared both in raw_object.h (for direct access
+  // from C++ code) and also here so that the offset-to-field map used by
+  // deferred objects is properly initialized.
+  // Caution: These fields are not Dart instances, but VM objects. Their Dart
+  // names do not need to match the C++ names, but they must be private.
+  @pragma("vm:entry-point")
+  var _instantiator_type_arguments;
+  @pragma("vm:entry-point")
+  var _function_type_arguments;
+  @pragma("vm:entry-point")
+  var _delayed_type_arguments;
+  @pragma("vm:entry-point")
+  var _function;
+  @pragma("vm:entry-point")
+  var _context;
+
+  // Note: _Closure objects are created by VM "magically", without invoking
+  // constructor. So, _Closure default constructor is never compiled and
+  // detection of default-initialized fields is not performed.
+  // As a consequence, VM incorrectly assumes that _hash field is not
+  // nullable and may incorrectly remove 'if (_hash == null)' in get:hashCode.
+  // This initializer makes _hash field nullable even without constructor
+  // compilation.
+  @pragma("vm:entry-point")
+  var _hash = null;
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/function_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/function_patch.dart
new file mode 100644
index 0000000..f5f73bd
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/function_patch.dart
@@ -0,0 +1,35 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+@patch
+class Function {
+  // TODO(regis): Pass type arguments to generic functions. Wait for API spec.
+  static _apply(List arguments, List names) native "Function_apply";
+
+  @patch
+  static apply(Function function, List positionalArguments,
+      [Map<Symbol, dynamic> namedArguments]) {
+    int numPositionalArguments = 1 + // Function is first implicit argument.
+        (positionalArguments != null ? positionalArguments.length : 0);
+    int numNamedArguments = namedArguments != null ? namedArguments.length : 0;
+    int numArguments = numPositionalArguments + numNamedArguments;
+    List arguments = new List(numArguments);
+    arguments[0] = function;
+    arguments.setRange(1, numPositionalArguments, positionalArguments);
+    List names = new List(numNamedArguments);
+    int argumentIndex = numPositionalArguments;
+    int nameIndex = 0;
+    if (numNamedArguments > 0) {
+      namedArguments.forEach((name, value) {
+        arguments[argumentIndex++] = value;
+        names[nameIndex++] = internal.Symbol.getName(name);
+      });
+    }
+    return _apply(arguments, names);
+  }
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/growable_array.dart b/sdk_nnbd/lib/_internal/vm/lib/growable_array.dart
new file mode 100644
index 0000000..851225b
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/growable_array.dart
@@ -0,0 +1,396 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+@pragma("vm:entry-point")
+class _GrowableList<T> extends ListBase<T> {
+  void insert(int index, T element) {
+    if ((index < 0) || (index > length)) {
+      throw new RangeError.range(index, 0, length);
+    }
+    if (index == this.length) {
+      add(element);
+      return;
+    }
+    int oldLength = this.length;
+    // We are modifying the length just below the is-check. Without the check
+    // Array.copy could throw an exception, leaving the list in a bad state
+    // (with a length that has been increased, but without a new element).
+    if (index is! int) throw new ArgumentError(index);
+    this.length++;
+    Lists.copy(this, index, this, index + 1, oldLength - index);
+    this[index] = element;
+  }
+
+  T removeAt(int index) {
+    var result = this[index];
+    int newLength = this.length - 1;
+    if (index < newLength) {
+      Lists.copy(this, index + 1, this, index, newLength - index);
+    }
+    this.length = newLength;
+    return result;
+  }
+
+  bool remove(Object element) {
+    for (int i = 0; i < this.length; i++) {
+      if (this[i] == element) {
+        removeAt(i);
+        return true;
+      }
+    }
+    return false;
+  }
+
+  void insertAll(int index, Iterable<T> iterable) {
+    if (index < 0 || index > length) {
+      throw new RangeError.range(index, 0, length);
+    }
+    // TODO(floitsch): we can probably detect more cases.
+    if (iterable is! List && iterable is! Set && iterable is! SubListIterable) {
+      iterable = iterable.toList();
+    }
+    int insertionLength = iterable.length;
+    // There might be errors after the length change, in which case the list
+    // will end up being modified but the operation not complete. Unless we
+    // always go through a "toList" we can't really avoid that.
+    this.length += insertionLength;
+    setRange(index + insertionLength, this.length, this, index);
+    setAll(index, iterable);
+  }
+
+  void setAll(int index, Iterable<T> iterable) {
+    if (iterable is List) {
+      setRange(index, index + iterable.length, iterable);
+    } else {
+      for (T element in iterable) {
+        this[index++] = element;
+      }
+    }
+  }
+
+  void removeRange(int start, int end) {
+    RangeError.checkValidRange(start, end, this.length);
+    Lists.copy(this, end, this, start, this.length - end);
+    this.length = this.length - (end - start);
+  }
+
+  List<T> sublist(int start, [int end]) {
+    end = RangeError.checkValidRange(start, end, this.length);
+    int length = end - start;
+    if (length == 0) return <T>[];
+    List list = new _List(length);
+    for (int i = 0; i < length; i++) {
+      list[i] = this[start + i];
+    }
+    var result = new _GrowableList<T>._withData(list);
+    result._setLength(length);
+    return result;
+  }
+
+  factory _GrowableList(int length) {
+    var data = _allocateData(length);
+    var result = new _GrowableList<T>._withData(data);
+    if (length > 0) {
+      result._setLength(length);
+    }
+    return result;
+  }
+
+  factory _GrowableList.withCapacity(int capacity) {
+    var data = _allocateData(capacity);
+    return new _GrowableList<T>._withData(data);
+  }
+
+  @pragma("vm:exact-result-type", _GrowableList)
+  factory _GrowableList._withData(_List data) native "GrowableList_allocate";
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  @pragma("vm:prefer-inline")
+  int get _capacity native "GrowableList_getCapacity";
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  @pragma("vm:prefer-inline")
+  int get length native "GrowableList_getLength";
+
+  void set length(int new_length) {
+    int old_capacity = _capacity;
+    int new_capacity = new_length;
+    if (new_capacity > old_capacity) {
+      _grow(new_capacity);
+      _setLength(new_length);
+      return;
+    }
+    // We are shrinking. Pick the method which has fewer writes.
+    // In the shrink-to-fit path, we write |new_capacity + new_length| words
+    // (null init + copy).
+    // In the non-shrink-to-fit path, we write |length - new_length| words
+    // (null overwrite).
+    final bool shouldShrinkToFit =
+        (new_capacity + new_length) < (length - new_length);
+    if (shouldShrinkToFit) {
+      _shrink(new_capacity, new_length);
+    } else {
+      for (int i = new_length; i < length; i++) {
+        this[i] = null;
+      }
+    }
+    _setLength(new_length);
+  }
+
+  void _setLength(int new_length) native "GrowableList_setLength";
+
+  void _setData(_List array) native "GrowableList_setData";
+
+  T operator [](int index) native "GrowableList_getIndexed";
+
+  void operator []=(int index, T value) {
+    _setIndexed(index, value);
+  }
+
+  void _setIndexed(int index, T value) native "GrowableList_setIndexed";
+
+  @pragma("vm:entry-point", "call")
+  @pragma("vm:prefer-inline")
+  void add(T value) {
+    var len = length;
+    if (len == _capacity) {
+      _grow(_nextCapacity(len));
+    }
+    _setLength(len + 1);
+    this[len] = value;
+  }
+
+  void addAll(Iterable<T> iterable) {
+    var len = length;
+    final cid = ClassID.getID(iterable);
+    final isVMList = (cid == ClassID.cidArray) ||
+        (cid == ClassID.cidGrowableObjectArray) ||
+        (cid == ClassID.cidImmutableArray);
+    if (isVMList || (iterable is EfficientLengthIterable)) {
+      var cap = _capacity;
+      // Pregrow if we know iterable.length.
+      var iterLen = iterable.length;
+      var newLen = len + iterLen;
+      if (newLen > cap) {
+        do {
+          cap = _nextCapacity(cap);
+        } while (newLen > cap);
+        _grow(cap);
+      }
+      if (isVMList) {
+        if (identical(iterable, this)) {
+          throw new ConcurrentModificationError(this);
+        }
+        this._setLength(newLen);
+        final ListBase<T> iterableAsList = iterable;
+        for (int i = 0; i < iterLen; i++) {
+          this[len++] = iterableAsList[i];
+        }
+        return;
+      }
+    }
+    Iterator it = iterable.iterator;
+    if (!it.moveNext()) return;
+    do {
+      while (len < _capacity) {
+        int newLen = len + 1;
+        this._setLength(newLen);
+        this[len] = it.current;
+        if (!it.moveNext()) return;
+        if (this.length != newLen) throw new ConcurrentModificationError(this);
+        len = newLen;
+      }
+      _grow(_nextCapacity(_capacity));
+    } while (true);
+  }
+
+  @pragma("vm:prefer-inline")
+  T removeLast() {
+    var len = length - 1;
+    var elem = this[len];
+    this.length = len;
+    return elem;
+  }
+
+  T get first {
+    if (length > 0) return this[0];
+    throw IterableElementError.noElement();
+  }
+
+  T get last {
+    if (length > 0) return this[length - 1];
+    throw IterableElementError.noElement();
+  }
+
+  T get single {
+    if (length == 1) return this[0];
+    if (length == 0) throw IterableElementError.noElement();
+    throw IterableElementError.tooMany();
+  }
+
+  // Shared array used as backing for new empty growable arrays.
+  static final _List _emptyList = new _List(0);
+
+  static _List _allocateData(int capacity) {
+    if (capacity == 0) {
+      // Use shared empty list as backing.
+      return _emptyList;
+    }
+    // Round up size to the next odd number, since this is free
+    // because of alignment requirements of the GC.
+    return new _List(capacity | 1);
+  }
+
+  // Grow from 0 to 3, and then double + 1.
+  int _nextCapacity(int old_capacity) => (old_capacity * 2) | 3;
+
+  void _grow(int new_capacity) {
+    var newData = _allocateData(new_capacity);
+    // This is a work-around for dartbug.com/30090: array-bound-check
+    // generalization causes excessive deoptimizations because it
+    // hoists CheckArrayBound(i, ...) out of the loop below and turns it
+    // into CheckArrayBound(length - 1, ...). Which deoptimizes
+    // if length == 0. However the loop itself does not execute
+    // if length == 0.
+    if (length > 0) {
+      for (int i = 0; i < length; i++) {
+        newData[i] = this[i];
+      }
+    }
+    _setData(newData);
+  }
+
+  void _shrink(int new_capacity, int new_length) {
+    var newData = _allocateData(new_capacity);
+    // This is a work-around for dartbug.com/30090. See the comment in _grow.
+    if (new_length > 0) {
+      for (int i = 0; i < new_length; i++) {
+        newData[i] = this[i];
+      }
+    }
+    _setData(newData);
+  }
+
+  // Iterable interface.
+
+  @pragma("vm:prefer-inline")
+  void forEach(f(T element)) {
+    int initialLength = length;
+    for (int i = 0; i < length; i++) {
+      f(this[i]);
+      if (length != initialLength) throw new ConcurrentModificationError(this);
+    }
+  }
+
+  String join([String separator = ""]) {
+    final int length = this.length;
+    if (length == 0) return "";
+    if (length == 1) return "${this[0]}";
+    if (separator.isNotEmpty) return _joinWithSeparator(separator);
+    var i = 0;
+    var codeUnitCount = 0;
+    while (i < length) {
+      final element = this[i];
+      // While list contains one-byte strings.
+      if (element is _OneByteString) {
+        codeUnitCount += element.length;
+        i++;
+        // Loop back while strings are one-byte strings.
+        continue;
+      }
+      // Otherwise, never loop back to the outer loop, and
+      // handle the remaining strings below.
+
+      // Loop while elements are strings,
+      final int firstNonOneByteStringLimit = i;
+      var nextElement = element;
+      while (nextElement is String) {
+        i++;
+        if (i == length) {
+          return _StringBase._concatRangeNative(this, 0, length);
+        }
+        nextElement = this[i];
+      }
+
+      // Not all elements are strings, so allocate a new backing array.
+      final list = new _List(length);
+      for (int copyIndex = 0; copyIndex < i; copyIndex++) {
+        list[copyIndex] = this[copyIndex];
+      }
+      // Is non-zero if list contains a non-onebyte string.
+      var onebyteCanary = i - firstNonOneByteStringLimit;
+      while (true) {
+        final String elementString = "$nextElement";
+        onebyteCanary |=
+            (ClassID.getID(elementString) ^ ClassID.cidOneByteString);
+        list[i] = elementString;
+        codeUnitCount += elementString.length;
+        i++;
+        if (i == length) break;
+        nextElement = this[i];
+      }
+      if (onebyteCanary == 0) {
+        // All elements returned a one-byte string from toString.
+        return _OneByteString._concatAll(list, codeUnitCount);
+      }
+      return _StringBase._concatRangeNative(list, 0, length);
+    }
+    // All elements were one-byte strings.
+    return _OneByteString._concatAll(this, codeUnitCount);
+  }
+
+  String _joinWithSeparator(String separator) {
+    StringBuffer buffer = new StringBuffer();
+    buffer.write(this[0]);
+    for (int i = 1; i < this.length; i++) {
+      buffer.write(separator);
+      buffer.write(this[i]);
+    }
+    return buffer.toString();
+  }
+
+  T elementAt(int index) {
+    return this[index];
+  }
+
+  bool get isEmpty {
+    return this.length == 0;
+  }
+
+  bool get isNotEmpty => !isEmpty;
+
+  void clear() {
+    this.length = 0;
+  }
+
+  String toString() => ListBase.listToString(this);
+
+  @pragma("vm:prefer-inline")
+  Iterator<T> get iterator {
+    return new ListIterator<T>(this);
+  }
+
+  List<T> toList({bool growable: true}) {
+    var length = this.length;
+    if (length > 0) {
+      List list = growable ? new _List(length) : new _List<T>(length);
+      for (int i = 0; i < length; i++) {
+        list[i] = this[i];
+      }
+      if (!growable) return list;
+      var result = new _GrowableList<T>._withData(list);
+      result._setLength(length);
+      return result;
+    }
+    return growable ? <T>[] : new List<T>(0);
+  }
+
+  Set<T> toSet() {
+    return new Set<T>.from(this);
+  }
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/identical_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/identical_patch.dart
new file mode 100644
index 0000000..68dd8c8
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/identical_patch.dart
@@ -0,0 +1,15 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+@patch
+@pragma("vm:exact-result-type", bool)
+bool identical(Object a, Object b) native "Identical_comparison";
+
+@patch
+@pragma("vm:entry-point", "call")
+int identityHashCode(Object object) => object._identityHashCode;
diff --git a/sdk_nnbd/lib/_internal/vm/lib/immutable_map.dart b/sdk_nnbd/lib/_internal/vm/lib/immutable_map.dart
new file mode 100644
index 0000000..08de90d
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/immutable_map.dart
@@ -0,0 +1,222 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+/// Immutable map class for compiler generated map literals.
+// TODO(lrn): Extend MapBase with UnmodifiableMapMixin when mixins
+// support forwarding const constructors.
+@pragma("vm:entry-point")
+class _ImmutableMap<K, V> implements Map<K, V> {
+  final _ImmutableList _kvPairs;
+
+  @pragma("vm:entry-point")
+  const _ImmutableMap._create(_ImmutableList keyValuePairs)
+      : _kvPairs = keyValuePairs;
+
+  Map<K2, V2> cast<K2, V2>() => Map.castFrom<K, V, K2, V2>(this);
+  V operator [](Object key) {
+    // To preserve the key-value order of the map literal, the keys are
+    // not sorted. Need to do linear search or implement an additional
+    // lookup table.
+    for (int i = 0; i < _kvPairs.length - 1; i += 2) {
+      if (key == _kvPairs[i]) {
+        return _kvPairs[i + 1];
+      }
+    }
+    return null;
+  }
+
+  bool get isEmpty {
+    return _kvPairs.length == 0;
+  }
+
+  bool get isNotEmpty => !isEmpty;
+
+  int get length {
+    return _kvPairs.length ~/ 2;
+  }
+
+  void forEach(void f(K key, V value)) {
+    for (int i = 0; i < _kvPairs.length; i += 2) {
+      f(_kvPairs[i], _kvPairs[i + 1]);
+    }
+  }
+
+  Iterable<K> get keys {
+    return new _ImmutableMapKeyIterable<K>(this);
+  }
+
+  Iterable<V> get values {
+    return new _ImmutableMapValueIterable<V>(this);
+  }
+
+  bool containsKey(Object key) {
+    for (int i = 0; i < _kvPairs.length; i += 2) {
+      if (key == _kvPairs[i]) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  bool containsValue(Object value) {
+    for (int i = 1; i < _kvPairs.length; i += 2) {
+      if (value == _kvPairs[i]) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  void operator []=(K key, V value) {
+    throw new UnsupportedError("Cannot set value in unmodifiable Map");
+  }
+
+  void addAll(Map<K, V> other) {
+    throw new UnsupportedError("Cannot set value in unmodifiable Map");
+  }
+
+  V putIfAbsent(K key, V ifAbsent()) {
+    throw new UnsupportedError("Cannot set value in unmodifiable Map");
+  }
+
+  void clear() {
+    throw new UnsupportedError("Cannot clear unmodifiable Map");
+  }
+
+  V remove(Object key) {
+    throw new UnsupportedError("Cannot remove from unmodifiable Map");
+  }
+
+  Iterable<MapEntry<K, V>> get entries =>
+      new _ImmutableMapEntryIterable<K, V>(this);
+
+  Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> f(K key, V value)) {
+    var result = <K2, V2>{};
+    for (int i = 0; i < _kvPairs.length; i += 2) {
+      var entry = f(_kvPairs[i], _kvPairs[i + 1]);
+      result[entry.key] = entry.value;
+    }
+    return result;
+  }
+
+  void addEntries(Iterable<MapEntry<K, V>> newEntries) {
+    throw new UnsupportedError("Cannot modify an unmodifiable Map");
+  }
+
+  V update(K key, V update(V value), {V ifAbsent()}) {
+    throw new UnsupportedError("Cannot modify an unmodifiable Map");
+  }
+
+  void updateAll(V update(K key, V value)) {
+    throw new UnsupportedError("Cannot modify an unmodifiable Map");
+  }
+
+  void removeWhere(bool predicate(K key, V value)) {
+    throw new UnsupportedError("Cannot modify an unmodifiable Map");
+  }
+
+  String toString() => MapBase.mapToString(this);
+}
+
+class _ImmutableMapKeyIterable<E> extends EfficientLengthIterable<E> {
+  final _ImmutableMap _map;
+  _ImmutableMapKeyIterable(this._map);
+
+  Iterator<E> get iterator {
+    return new _ImmutableMapKeyIterator<E>(_map);
+  }
+
+  int get length => _map.length;
+}
+
+class _ImmutableMapValueIterable<E> extends EfficientLengthIterable<E> {
+  final _ImmutableMap _map;
+  _ImmutableMapValueIterable(this._map);
+
+  Iterator<E> get iterator {
+    return new _ImmutableMapValueIterator<E>(_map);
+  }
+
+  int get length => _map.length;
+}
+
+class _ImmutableMapEntryIterable<K, V>
+    extends EfficientLengthIterable<MapEntry<K, V>> {
+  final _ImmutableMap _map;
+  _ImmutableMapEntryIterable(this._map);
+
+  Iterator<MapEntry<K, V>> get iterator {
+    return new _ImmutableMapEntryIterator<K, V>(_map);
+  }
+
+  int get length => _map.length;
+}
+
+class _ImmutableMapKeyIterator<E> implements Iterator<E> {
+  _ImmutableMap _map;
+  int _nextIndex = 0;
+  E _current;
+
+  _ImmutableMapKeyIterator(this._map);
+
+  bool moveNext() {
+    int newIndex = _nextIndex;
+    if (newIndex < _map.length) {
+      _nextIndex = newIndex + 1;
+      _current = _map._kvPairs[newIndex * 2];
+      return true;
+    }
+    _current = null;
+    return false;
+  }
+
+  E get current => _current;
+}
+
+class _ImmutableMapValueIterator<E> implements Iterator<E> {
+  _ImmutableMap _map;
+  int _nextIndex = 0;
+  E _current;
+
+  _ImmutableMapValueIterator(this._map);
+
+  bool moveNext() {
+    int newIndex = _nextIndex;
+    if (newIndex < _map.length) {
+      _nextIndex = newIndex + 1;
+      _current = _map._kvPairs[newIndex * 2 + 1];
+      return true;
+    }
+    _current = null;
+    return false;
+  }
+
+  E get current => _current;
+}
+
+class _ImmutableMapEntryIterator<K, V> implements Iterator<MapEntry<K, V>> {
+  _ImmutableMap _map;
+  int _nextIndex = 0;
+  MapEntry<K, V> _current;
+
+  _ImmutableMapEntryIterator(this._map);
+
+  bool moveNext() {
+    int newIndex = _nextIndex;
+    if (newIndex < _map.length) {
+      _nextIndex = newIndex + 1;
+      _current = new MapEntry<K, V>(
+          _map._kvPairs[newIndex * 2], _map._kvPairs[newIndex * 2 + 1]);
+      return true;
+    }
+    _current = null;
+    return false;
+  }
+
+  MapEntry<K, V> get current => _current;
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/integers.dart b/sdk_nnbd/lib/_internal/vm/lib/integers.dart
new file mode 100644
index 0000000..fb2dd30
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/integers.dart
@@ -0,0 +1,722 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+abstract class _IntegerImplementation implements int {
+  @pragma("vm:non-nullable-result-type")
+  @pragma("vm:never-inline")
+  num operator +(num other) => other._addFromInteger(this);
+  @pragma("vm:non-nullable-result-type")
+  @pragma("vm:never-inline")
+  num operator -(num other) => other._subFromInteger(this);
+  @pragma("vm:non-nullable-result-type")
+  @pragma("vm:never-inline")
+  num operator *(num other) => other._mulFromInteger(this);
+
+  @pragma("vm:non-nullable-result-type")
+  @pragma("vm:never-inline")
+  int operator ~/(num other) {
+    if ((other is int) && (other == 0)) {
+      throw const IntegerDivisionByZeroException();
+    }
+    return other._truncDivFromInteger(this);
+  }
+
+  double operator /(num other) {
+    return this.toDouble() / other.toDouble();
+  }
+
+  @pragma("vm:non-nullable-result-type")
+  num operator %(num other) {
+    if ((other is int) && (other == 0)) {
+      throw const IntegerDivisionByZeroException();
+    }
+    return other._moduloFromInteger(this);
+  }
+
+  @pragma("vm:non-nullable-result-type")
+  @pragma("vm:never-inline")
+  int operator -() {
+    return 0 - this;
+  }
+
+  @pragma("vm:non-nullable-result-type")
+  @pragma("vm:never-inline")
+  int operator &(int other) => other._bitAndFromInteger(this);
+  @pragma("vm:non-nullable-result-type")
+  @pragma("vm:never-inline")
+  int operator |(int other) => other._bitOrFromInteger(this);
+  @pragma("vm:non-nullable-result-type")
+  @pragma("vm:never-inline")
+  int operator ^(int other) => other._bitXorFromInteger(this);
+
+  num remainder(num other) {
+    return other._remainderFromInteger(this);
+  }
+
+  @pragma("vm:non-nullable-result-type")
+  int _bitAndFromSmi(_Smi other) native "Integer_bitAndFromInteger";
+  @pragma("vm:non-nullable-result-type")
+  int _bitAndFromInteger(int other) native "Integer_bitAndFromInteger";
+  @pragma("vm:non-nullable-result-type")
+  int _bitOrFromInteger(int other) native "Integer_bitOrFromInteger";
+  @pragma("vm:non-nullable-result-type")
+  int _bitXorFromInteger(int other) native "Integer_bitXorFromInteger";
+  @pragma("vm:non-nullable-result-type")
+  int _shrFromInteger(int other) native "Integer_shrFromInteger";
+  @pragma("vm:non-nullable-result-type")
+  int _shlFromInteger(int other) native "Integer_shlFromInteger";
+  @pragma("vm:non-nullable-result-type")
+  int _addFromInteger(int other) native "Integer_addFromInteger";
+  @pragma("vm:non-nullable-result-type")
+  int _subFromInteger(int other) native "Integer_subFromInteger";
+  @pragma("vm:non-nullable-result-type")
+  int _mulFromInteger(int other) native "Integer_mulFromInteger";
+  @pragma("vm:non-nullable-result-type")
+  int _truncDivFromInteger(int other) native "Integer_truncDivFromInteger";
+  @pragma("vm:non-nullable-result-type")
+  int _moduloFromInteger(int other) native "Integer_moduloFromInteger";
+  int _remainderFromInteger(int other) {
+    return other - (other ~/ this) * this;
+  }
+
+  @pragma("vm:non-nullable-result-type")
+  @pragma("vm:never-inline")
+  int operator >>(int other) => other._shrFromInteger(this);
+  @pragma("vm:non-nullable-result-type")
+  @pragma("vm:never-inline")
+  int operator <<(int other) => other._shlFromInteger(this);
+
+  @pragma("vm:exact-result-type", bool)
+  @pragma("vm:never-inline")
+  bool operator <(num other) {
+    return other > this;
+  }
+
+  @pragma("vm:exact-result-type", bool)
+  @pragma("vm:never-inline")
+  bool operator >(num other) {
+    return other._greaterThanFromInteger(this);
+  }
+
+  @pragma("vm:exact-result-type", bool)
+  @pragma("vm:never-inline")
+  bool operator >=(num other) {
+    return (this == other) || (this > other);
+  }
+
+  @pragma("vm:exact-result-type", bool)
+  @pragma("vm:never-inline")
+  bool operator <=(num other) {
+    return (this == other) || (this < other);
+  }
+
+  @pragma("vm:exact-result-type", bool)
+  bool _greaterThanFromInteger(int other)
+      native "Integer_greaterThanFromInteger";
+
+  @pragma("vm:exact-result-type", bool)
+  @pragma("vm:never-inline")
+  bool operator ==(Object other) {
+    if (other is num) {
+      return other._equalToInteger(this);
+    }
+    return false;
+  }
+
+  @pragma("vm:exact-result-type", bool)
+  bool _equalToInteger(int other) native "Integer_equalToInteger";
+  int abs() {
+    return this < 0 ? -this : this;
+  }
+
+  int get sign {
+    return (this > 0) ? 1 : (this < 0) ? -1 : 0;
+  }
+
+  bool get isEven => ((this & 1) == 0);
+  bool get isOdd => !isEven;
+  bool get isNaN => false;
+  bool get isNegative => this < 0;
+  bool get isInfinite => false;
+  bool get isFinite => true;
+
+  int toUnsigned(int width) {
+    return this & ((1 << width) - 1);
+  }
+
+  int toSigned(int width) {
+    // The value of binary number weights each bit by a power of two.  The
+    // twos-complement value weights the sign bit negatively.  We compute the
+    // value of the negative weighting by isolating the sign bit with the
+    // correct power of two weighting and subtracting it from the value of the
+    // lower bits.
+    int signMask = 1 << (width - 1);
+    return (this & (signMask - 1)) - (this & signMask);
+  }
+
+  int compareTo(num other) {
+    const int EQUAL = 0, LESS = -1, GREATER = 1;
+    if (other is double) {
+      const int MAX_EXACT_INT_TO_DOUBLE = 9007199254740992; // 2^53.
+      const int MIN_EXACT_INT_TO_DOUBLE = -MAX_EXACT_INT_TO_DOUBLE;
+      const bool limitIntsTo64Bits = ((1 << 64) == 0);
+      if (limitIntsTo64Bits) {
+        // With integers limited to 64 bits, double.toInt() clamps
+        // double value to fit into the MIN_INT64..MAX_INT64 range.
+        // Check if the double value is outside of this range.
+        // This check handles +/-infinity as well.
+        const double minInt64AsDouble = -9223372036854775808.0;
+        // MAX_INT64 is not precisely representable in doubles, so
+        // check against (MAX_INT64 + 1).
+        const double maxInt64Plus1AsDouble = 9223372036854775808.0;
+        if (other < minInt64AsDouble) {
+          return GREATER;
+        } else if (other >= maxInt64Plus1AsDouble) {
+          return LESS;
+        }
+      } else {
+        if (other.isInfinite) {
+          return other.isNegative ? GREATER : LESS;
+        }
+      }
+      if (other.isNaN) {
+        return LESS;
+      }
+      if (MIN_EXACT_INT_TO_DOUBLE <= this && this <= MAX_EXACT_INT_TO_DOUBLE) {
+        // Let the double implementation deal with -0.0.
+        return -(other.compareTo(this.toDouble()));
+      } else {
+        // If abs(other) > MAX_EXACT_INT_TO_DOUBLE, then other has an integer
+        // value (no bits below the decimal point).
+        other = other.toInt();
+      }
+    }
+    if (this < other) {
+      return LESS;
+    } else if (this > other) {
+      return GREATER;
+    } else {
+      return EQUAL;
+    }
+  }
+
+  int round() {
+    return this;
+  }
+
+  int floor() {
+    return this;
+  }
+
+  int ceil() {
+    return this;
+  }
+
+  int truncate() {
+    return this;
+  }
+
+  double roundToDouble() {
+    return this.toDouble();
+  }
+
+  double floorToDouble() {
+    return this.toDouble();
+  }
+
+  double ceilToDouble() {
+    return this.toDouble();
+  }
+
+  double truncateToDouble() {
+    return this.toDouble();
+  }
+
+  num clamp(num lowerLimit, num upperLimit) {
+    if (lowerLimit is! num) {
+      throw new ArgumentError.value(lowerLimit, "lowerLimit", "not a number");
+    }
+    if (upperLimit is! num) {
+      throw new ArgumentError.value(upperLimit, "upperLimit", "not a number");
+    }
+
+    // Special case for integers.
+    if (lowerLimit is int && upperLimit is int && lowerLimit <= upperLimit) {
+      if (this < lowerLimit) return lowerLimit;
+      if (this > upperLimit) return upperLimit;
+      return this;
+    }
+    // Generic case involving doubles, and invalid integer ranges.
+    if (lowerLimit.compareTo(upperLimit) > 0) {
+      throw new ArgumentError(lowerLimit);
+    }
+    if (lowerLimit.isNaN) return lowerLimit;
+    // Note that we don't need to care for -0.0 for the lower limit.
+    if (this < lowerLimit) return lowerLimit;
+    if (this.compareTo(upperLimit) > 0) return upperLimit;
+    return this;
+  }
+
+  int toInt() {
+    return this;
+  }
+
+  @pragma("vm:exact-result-type", _Double)
+  double toDouble() {
+    return new _Double.fromInteger(this);
+  }
+
+  String toStringAsFixed(int fractionDigits) {
+    return this.toDouble().toStringAsFixed(fractionDigits);
+  }
+
+  String toStringAsExponential([int fractionDigits]) {
+    return this.toDouble().toStringAsExponential(fractionDigits);
+  }
+
+  String toStringAsPrecision(int precision) {
+    return this.toDouble().toStringAsPrecision(precision);
+  }
+
+  static const _digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+
+  String toRadixString(int radix) {
+    if (radix < 2 || 36 < radix) {
+      throw new RangeError.range(radix, 2, 36, "radix");
+    }
+    if (radix & (radix - 1) == 0) {
+      return _toPow2String(radix);
+    }
+    if (radix == 10) return this.toString();
+    final bool isNegative = this < 0;
+    int value = isNegative ? -this : this;
+    if (value < 0) {
+      // With integers limited to 64 bits, the value
+      // MIN_INT64 = -0x8000000000000000 overflows at negation:
+      // -MIN_INT64 == MIN_INT64, so it requires special handling.
+      return _minInt64ToRadixString(radix);
+    }
+    List temp = new List();
+    do {
+      int digit = value % radix;
+      value ~/= radix;
+      temp.add(_digits.codeUnitAt(digit));
+    } while (value > 0);
+    if (isNegative) temp.add(0x2d); // '-'.
+
+    _OneByteString string = _OneByteString._allocate(temp.length);
+    for (int i = 0, j = temp.length; j > 0; i++) {
+      string._setAt(i, temp[--j]);
+    }
+    return string;
+  }
+
+  String _toPow2String(int radix) {
+    int value = this;
+    if (value == 0) return "0";
+    assert(radix & (radix - 1) == 0);
+    var negative = value < 0;
+    var bitsPerDigit = radix.bitLength - 1;
+    var length = 0;
+    if (negative) {
+      value = -value;
+      length = 1;
+      if (value < 0) {
+        // With integers limited to 64 bits, the value
+        // MIN_INT64 = -0x8000000000000000 overflows at negation:
+        // -MIN_INT64 == MIN_INT64, so it requires special handling.
+        return _minInt64ToRadixString(radix);
+      }
+    }
+    // Integer division, rounding up, to find number of _digits.
+    length += (value.bitLength + bitsPerDigit - 1) ~/ bitsPerDigit;
+    _OneByteString string = _OneByteString._allocate(length);
+    string._setAt(0, 0x2d); // '-'. Is overwritten if not negative.
+    var mask = radix - 1;
+    do {
+      string._setAt(--length, _digits.codeUnitAt(value & mask));
+      value >>= bitsPerDigit;
+    } while (value > 0);
+    return string;
+  }
+
+  /// Converts negative value to radix string.
+  /// This method is only used to handle corner case of
+  /// MIN_INT64 = -0x8000000000000000.
+  String _minInt64ToRadixString(int radix) {
+    List temp = new List();
+    int value = this;
+    assert(value < 0);
+    do {
+      int digit = -value.remainder(radix);
+      value ~/= radix;
+      temp.add(_digits.codeUnitAt(digit));
+    } while (value != 0);
+    temp.add(0x2d); // '-'.
+
+    _OneByteString string = _OneByteString._allocate(temp.length);
+    for (int i = 0, j = temp.length; j > 0; i++) {
+      string._setAt(i, temp[--j]);
+    }
+    return string;
+  }
+
+  // Returns pow(this, e) % m.
+  int modPow(int e, int m) {
+    if (e is! int) {
+      throw new ArgumentError.value(e, "exponent", "not an integer");
+    }
+    if (m is! int) {
+      throw new ArgumentError.value(m, "modulus", "not an integer");
+    }
+    if (e < 0) throw new RangeError.range(e, 0, null, "exponent");
+    if (m <= 0) throw new RangeError.range(m, 1, null, "modulus");
+    if (e == 0) return 1;
+
+    // This is floor(sqrt(2^63)).
+    const int maxValueThatCanBeSquaredWithoutTruncation = 3037000499;
+    if (m > maxValueThatCanBeSquaredWithoutTruncation) {
+      // Use BigInt version to avoid truncation in multiplications below.
+      return BigInt.from(this).modPow(BigInt.from(e), BigInt.from(m)).toInt();
+    }
+
+    int b = this;
+    if (b < 0 || b > m) {
+      b %= m;
+    }
+    int r = 1;
+    while (e > 0) {
+      if (e.isOdd) {
+        r = (r * b) % m;
+      }
+      e >>= 1;
+      b = (b * b) % m;
+    }
+    return r;
+  }
+
+  // If inv is false, returns gcd(x, y).
+  // If inv is true and gcd(x, y) = 1, returns d, so that c*x + d*y = 1.
+  // If inv is true and gcd(x, y) != 1, throws Exception("Not coprime").
+  static int _binaryGcd(int x, int y, bool inv) {
+    int s = 0;
+    if (!inv) {
+      while (x.isEven && y.isEven) {
+        x >>= 1;
+        y >>= 1;
+        s++;
+      }
+      if (y.isOdd) {
+        var t = x;
+        x = y;
+        y = t;
+      }
+    }
+    final bool ac = x.isEven;
+    int u = x;
+    int v = y;
+    int a = 1, b = 0, c = 0, d = 1;
+    do {
+      while (u.isEven) {
+        u >>= 1;
+        if (ac) {
+          if (!a.isEven || !b.isEven) {
+            a += y;
+            b -= x;
+          }
+          a >>= 1;
+        } else if (!b.isEven) {
+          b -= x;
+        }
+        b >>= 1;
+      }
+      while (v.isEven) {
+        v >>= 1;
+        if (ac) {
+          if (!c.isEven || !d.isEven) {
+            c += y;
+            d -= x;
+          }
+          c >>= 1;
+        } else if (!d.isEven) {
+          d -= x;
+        }
+        d >>= 1;
+      }
+      if (u >= v) {
+        u -= v;
+        if (ac) a -= c;
+        b -= d;
+      } else {
+        v -= u;
+        if (ac) c -= a;
+        d -= b;
+      }
+    } while (u != 0);
+    if (!inv) return v << s;
+    if (v != 1) {
+      throw new Exception("Not coprime");
+    }
+    if (d < 0) {
+      d += x;
+      if (d < 0) d += x;
+    } else if (d > x) {
+      d -= x;
+      if (d > x) d -= x;
+    }
+    return d;
+  }
+
+  // Returns 1/this % m, with m > 0.
+  int modInverse(int m) {
+    if (m is! int) {
+      throw new ArgumentError.value(m, "modulus", "not an integer");
+    }
+    if (m <= 0) throw new RangeError.range(m, 1, null, "modulus");
+    if (m == 1) return 0;
+    int t = this;
+    if ((t < 0) || (t >= m)) t %= m;
+    if (t == 1) return 1;
+    if ((t == 0) || (t.isEven && m.isEven)) {
+      throw new Exception("Not coprime");
+    }
+    return _binaryGcd(m, t, true);
+  }
+
+  // Returns gcd of abs(this) and abs(other).
+  int gcd(int other) {
+    if (other is! int) {
+      throw new ArgumentError.value(other, "other", "not an integer");
+    }
+    int x = this.abs();
+    int y = other.abs();
+    if (x == 0) return y;
+    if (y == 0) return x;
+    if ((x == 1) || (y == 1)) return 1;
+    return _binaryGcd(x, y, false);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Smi extends _IntegerImplementation {
+  factory _Smi._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  int get hashCode => this;
+  int get _identityHashCode => this;
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  int operator ~() native "Smi_bitNegate";
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  int get bitLength native "Smi_bitLength";
+
+  int operator &(int other) => other._bitAndFromSmi(this);
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  int _bitAndFromSmi(_Smi other) native "Smi_bitAndFromSmi";
+
+  /**
+   * The digits of '00', '01', ... '99' as a single array.
+   *
+   * Get the digits of `n`, with `0 <= n < 100`, as
+   * `_digitTable[n * 2]` and `_digitTable[n * 2 + 1]`.
+   */
+  static const _digitTable = const [
+    0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, //
+    0x30, 0x34, 0x30, 0x35, 0x30, 0x36, 0x30, 0x37, //
+    0x30, 0x38, 0x30, 0x39, 0x31, 0x30, 0x31, 0x31, //
+    0x31, 0x32, 0x31, 0x33, 0x31, 0x34, 0x31, 0x35, //
+    0x31, 0x36, 0x31, 0x37, 0x31, 0x38, 0x31, 0x39, //
+    0x32, 0x30, 0x32, 0x31, 0x32, 0x32, 0x32, 0x33, //
+    0x32, 0x34, 0x32, 0x35, 0x32, 0x36, 0x32, 0x37, //
+    0x32, 0x38, 0x32, 0x39, 0x33, 0x30, 0x33, 0x31, //
+    0x33, 0x32, 0x33, 0x33, 0x33, 0x34, 0x33, 0x35, //
+    0x33, 0x36, 0x33, 0x37, 0x33, 0x38, 0x33, 0x39, //
+    0x34, 0x30, 0x34, 0x31, 0x34, 0x32, 0x34, 0x33, //
+    0x34, 0x34, 0x34, 0x35, 0x34, 0x36, 0x34, 0x37, //
+    0x34, 0x38, 0x34, 0x39, 0x35, 0x30, 0x35, 0x31, //
+    0x35, 0x32, 0x35, 0x33, 0x35, 0x34, 0x35, 0x35, //
+    0x35, 0x36, 0x35, 0x37, 0x35, 0x38, 0x35, 0x39, //
+    0x36, 0x30, 0x36, 0x31, 0x36, 0x32, 0x36, 0x33, //
+    0x36, 0x34, 0x36, 0x35, 0x36, 0x36, 0x36, 0x37, //
+    0x36, 0x38, 0x36, 0x39, 0x37, 0x30, 0x37, 0x31, //
+    0x37, 0x32, 0x37, 0x33, 0x37, 0x34, 0x37, 0x35, //
+    0x37, 0x36, 0x37, 0x37, 0x37, 0x38, 0x37, 0x39, //
+    0x38, 0x30, 0x38, 0x31, 0x38, 0x32, 0x38, 0x33, //
+    0x38, 0x34, 0x38, 0x35, 0x38, 0x36, 0x38, 0x37, //
+    0x38, 0x38, 0x38, 0x39, 0x39, 0x30, 0x39, 0x31, //
+    0x39, 0x32, 0x39, 0x33, 0x39, 0x34, 0x39, 0x35, //
+    0x39, 0x36, 0x39, 0x37, 0x39, 0x38, 0x39, 0x39, //
+  ];
+
+  /**
+   * Result of int.toString for -99, -98, ..., 98, 99.
+   */
+  static const _smallLookupTable = const [
+    "-99", "-98", "-97", "-96", "-95", "-94", "-93", "-92", "-91", "-90", //
+    "-89", "-88", "-87", "-86", "-85", "-84", "-83", "-82", "-81", "-80", //
+    "-79", "-78", "-77", "-76", "-75", "-74", "-73", "-72", "-71", "-70", //
+    "-69", "-68", "-67", "-66", "-65", "-64", "-63", "-62", "-61", "-60", //
+    "-59", "-58", "-57", "-56", "-55", "-54", "-53", "-52", "-51", "-50", //
+    "-49", "-48", "-47", "-46", "-45", "-44", "-43", "-42", "-41", "-40", //
+    "-39", "-38", "-37", "-36", "-35", "-34", "-33", "-32", "-31", "-30", //
+    "-29", "-28", "-27", "-26", "-25", "-24", "-23", "-22", "-21", "-20", //
+    "-19", "-18", "-17", "-16", "-15", "-14", "-13", "-12", "-11", "-10", //
+    "-9", "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1", "0", //
+    "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", //
+    "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", //
+    "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", //
+    "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", //
+    "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", //
+    "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", //
+    "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", //
+    "71", "72", "73", "74", "75", "76", "77", "78", "79", "80", //
+    "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", //
+    "91", "92", "93", "94", "95", "96", "97", "98", "99" //
+  ];
+
+  // Powers of 10 above 1000000 are indistinguishable by eye.
+  static const int _POW_10_7 = 10000000;
+  static const int _POW_10_8 = 100000000;
+  static const int _POW_10_9 = 1000000000;
+
+  // Find the number of decimal digits in a positive smi.
+  // Never called with numbers < 100. These are handled before calling.
+  static int _positiveBase10Length(var smi) {
+    // A positive smi has length <= 19 if 63-bit,  <=10 if 31-bit.
+    // Avoid comparing a 31-bit smi to a non-smi.
+    if (smi < 1000) return 3;
+    if (smi < 10000) return 4;
+    if (smi < _POW_10_7) {
+      if (smi < 100000) return 5;
+      if (smi < 1000000) return 6;
+      return 7;
+    }
+    if (smi < _POW_10_8) return 8;
+    if (smi < _POW_10_9) return 9;
+    smi = smi ~/ _POW_10_9;
+    // Handle numbers < 100 before calling recursively.
+    if (smi < 10) return 10;
+    if (smi < 100) return 11;
+    return 9 + _positiveBase10Length(smi);
+  }
+
+  String toString() {
+    if (this < 100 && this > -100) return _smallLookupTable[this + 99];
+    if (this < 0) return _negativeToString(this);
+    // Inspired by Andrei Alexandrescu: "Three Optimization Tips for C++"
+    // Avoid expensive remainder operation by doing it on more than
+    // one digit at a time.
+    const int DIGIT_ZERO = 0x30;
+    int length = _positiveBase10Length(this);
+    _OneByteString result = _OneByteString._allocate(length);
+    int index = length - 1;
+    var smi = this;
+    do {
+      // Two digits at a time.
+      var twoDigits = smi.remainder(100);
+      smi = smi ~/ 100;
+      int digitIndex = twoDigits * 2;
+      result._setAt(index, _digitTable[digitIndex + 1]);
+      result._setAt(index - 1, _digitTable[digitIndex]);
+      index -= 2;
+    } while (smi >= 100);
+    if (smi < 10) {
+      // Character code for '0'.
+      result._setAt(index, DIGIT_ZERO + smi);
+    } else {
+      // No remainder for this case.
+      int digitIndex = smi * 2;
+      result._setAt(index, _digitTable[digitIndex + 1]);
+      result._setAt(index - 1, _digitTable[digitIndex]);
+    }
+    return result;
+  }
+
+  // Find the number of decimal digits in a negative smi.
+  // Never called with numbers > -100. These are handled before calling.
+  static int _negativeBase10Length(var negSmi) {
+    // A negative smi has length <= 19 if 63-bit, <=10 if 31-bit.
+    // Avoid comparing a 31-bit smi to a non-smi.
+    if (negSmi > -1000) return 3;
+    if (negSmi > -10000) return 4;
+    if (negSmi > -_POW_10_7) {
+      if (negSmi > -100000) return 5;
+      if (negSmi > -1000000) return 6;
+      return 7;
+    }
+    if (negSmi > -_POW_10_8) return 8;
+    if (negSmi > -_POW_10_9) return 9;
+    negSmi = negSmi ~/ _POW_10_9;
+    // Handle numbers > -100 before calling recursively.
+    if (negSmi > -10) return 10;
+    if (negSmi > -100) return 11;
+    return 9 + _negativeBase10Length(negSmi);
+  }
+
+  // Convert a negative smi to a string.
+  // Doesn't negate the smi to avoid negating the most negative smi, which
+  // would become a non-smi.
+  static String _negativeToString(int negSmi) {
+    // Character code for '-'
+    const int MINUS_SIGN = 0x2d;
+    // Character code for '0'.
+    const int DIGIT_ZERO = 0x30;
+    if (negSmi > -10) {
+      return _OneByteString._allocate(2)
+        .._setAt(0, MINUS_SIGN)
+        .._setAt(1, DIGIT_ZERO - negSmi);
+    }
+    if (negSmi > -100) {
+      int digitIndex = 2 * -negSmi;
+      return _OneByteString._allocate(3)
+        .._setAt(0, MINUS_SIGN)
+        .._setAt(1, _digitTable[digitIndex])
+        .._setAt(2, _digitTable[digitIndex + 1]);
+    }
+    // Number of digits, not including minus.
+    int digitCount = _negativeBase10Length(negSmi);
+    _OneByteString result = _OneByteString._allocate(digitCount + 1);
+    result._setAt(0, MINUS_SIGN); // '-'.
+    int index = digitCount;
+    do {
+      var twoDigits = negSmi.remainder(100);
+      negSmi = negSmi ~/ 100;
+      int digitIndex = -twoDigits * 2;
+      result._setAt(index, _digitTable[digitIndex + 1]);
+      result._setAt(index - 1, _digitTable[digitIndex]);
+      index -= 2;
+    } while (negSmi <= -100);
+    if (negSmi > -10) {
+      result._setAt(index, DIGIT_ZERO - negSmi);
+    } else {
+      // No remainder necessary for this case.
+      int digitIndex = -negSmi * 2;
+      result._setAt(index, _digitTable[digitIndex + 1]);
+      result._setAt(index - 1, _digitTable[digitIndex]);
+    }
+    return result;
+  }
+}
+
+// Represents integers that cannot be represented by Smi but fit into 64bits.
+@pragma("vm:entry-point")
+class _Mint extends _IntegerImplementation {
+  factory _Mint._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  int get hashCode => this;
+  int get _identityHashCode => this;
+  @pragma("vm:non-nullable-result-type")
+  int operator ~() native "Mint_bitNegate";
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  int get bitLength native "Mint_bitLength";
+
+  int _bitAndFromSmi(_Smi other) => _bitAndFromInteger(other);
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/integers_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/integers_patch.dart
new file mode 100644
index 0000000..48f528d6
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/integers_patch.dart
@@ -0,0 +1,308 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+/// VM implementation of int.
+@patch
+class int {
+  @patch
+  const factory int.fromEnvironment(String name, {int defaultValue})
+      native "Integer_fromEnvironment";
+
+  int _bitAndFromSmi(_Smi other);
+  int _bitAndFromInteger(int other);
+  int _bitOrFromInteger(int other);
+  int _bitXorFromInteger(int other);
+  int _shrFromInteger(int other);
+  int _shlFromInteger(int other);
+
+  static int _tryParseSmi(String str, int first, int last) {
+    assert(first <= last);
+    var ix = first;
+    var sign = 1;
+    var c = str.codeUnitAt(ix);
+    // Check for leading '+' or '-'.
+    if ((c == 0x2b) || (c == 0x2d)) {
+      ix++;
+      sign = 0x2c - c; // -1 for '-', +1 for '+'.
+      if (ix > last) {
+        return null; // Empty.
+      }
+    }
+    var smiLimit = is64Bit ? 18 : 9;
+    if ((last - ix) >= smiLimit) {
+      return null; // May not fit into a Smi.
+    }
+    var result = 0;
+    for (int i = ix; i <= last; i++) {
+      var c = 0x30 ^ str.codeUnitAt(i);
+      if (9 < c) {
+        return null;
+      }
+      result = 10 * result + c;
+    }
+    return sign * result;
+  }
+
+  @patch
+  static int parse(String source, {int radix, int onError(String source)}) {
+    if (source == null) throw new ArgumentError("The source must not be null");
+    if (source.isEmpty) {
+      return _throwFormatException(onError, source, 0, radix, null);
+    }
+    if (radix == null || radix == 10) {
+      // Try parsing immediately, without trimming whitespace.
+      int result = _tryParseSmi(source, 0, source.length - 1);
+      if (result != null) return result;
+    } else if (radix < 2 || radix > 36) {
+      throw new RangeError("Radix $radix not in range 2..36");
+    }
+    // Split here so improve odds of parse being inlined and the checks omitted.
+    return _parse(source, radix, onError);
+  }
+
+  static int _parse(_StringBase source, int radix, onError) {
+    int end = source._lastNonWhitespace() + 1;
+    if (end == 0) {
+      return _throwFormatException(onError, source, source.length, radix, null);
+    }
+    int start = source._firstNonWhitespace();
+
+    int first = source.codeUnitAt(start);
+    int sign = 1;
+    if (first == 0x2b /* + */ || first == 0x2d /* - */) {
+      sign = 0x2c - first; // -1 if '-', +1 if '+'.
+      start++;
+      if (start == end) {
+        return _throwFormatException(onError, source, end, radix, null);
+      }
+      first = source.codeUnitAt(start);
+    }
+    if (radix == null) {
+      // check for 0x prefix.
+      int index = start;
+      if (first == 0x30 /* 0 */) {
+        index++;
+        if (index == end) return 0;
+        first = source.codeUnitAt(index);
+        if ((first | 0x20) == 0x78 /* x */) {
+          index++;
+          if (index == end) {
+            return _throwFormatException(onError, source, index, null, null);
+          }
+          return _parseRadix(source, 16, index, end, sign, sign > 0, onError);
+        }
+      }
+      radix = 10;
+    }
+    return _parseRadix(source, radix, start, end, sign, false, onError);
+  }
+
+  @patch
+  static int tryParse(String source, {int radix}) {
+    if (source == null) throw new ArgumentError("The source must not be null");
+    if (source.isEmpty) return null;
+    if (radix == null || radix == 10) {
+      // Try parsing immediately, without trimming whitespace.
+      int result = _tryParseSmi(source, 0, source.length - 1);
+      if (result != null) return result;
+    } else if (radix < 2 || radix > 36) {
+      throw new RangeError("Radix $radix not in range 2..36");
+    }
+    try {
+      return _parse(source, radix, _kNull);
+    } catch (e) {
+      return null;
+    }
+  }
+
+  static Null _kNull(_) => null;
+
+  static int _throwFormatException(onError, source, index, radix, message) {
+    if (onError != null) return onError(source);
+    if (message != null) {
+      throw new FormatException(message, source, index);
+    }
+    if (radix == null) {
+      throw new FormatException("Invalid number", source, index);
+    }
+    throw new FormatException("Invalid radix-$radix number", source, index);
+  }
+
+  static int _parseRadix(String source, int radix, int start, int end, int sign,
+      bool allowU64, onError) {
+    int tableIndex = (radix - 2) * 4 + (is64Bit ? 2 : 0);
+    int blockSize = _PARSE_LIMITS[tableIndex];
+    int length = end - start;
+    if (length <= blockSize) {
+      _Smi smi = _parseBlock(source, radix, start, end);
+      if (smi == null) {
+        return _throwFormatException(onError, source, start, radix, null);
+      }
+      return sign * smi;
+    }
+
+    // Often cheaper than: int smallBlockSize = length % blockSize;
+    // because digit count generally tends towards smaller. rather
+    // than larger.
+    int smallBlockSize = length;
+    while (smallBlockSize >= blockSize) smallBlockSize -= blockSize;
+    int result = 0;
+    if (smallBlockSize > 0) {
+      int blockEnd = start + smallBlockSize;
+      _Smi smi = _parseBlock(source, radix, start, blockEnd);
+      if (smi == null) {
+        return _throwFormatException(onError, source, start, radix, null);
+      }
+      result = sign * smi;
+      start = blockEnd;
+    }
+    int multiplier = _PARSE_LIMITS[tableIndex + 1];
+    int positiveOverflowLimit = 0;
+    int negativeOverflowLimit = 0;
+    tableIndex = tableIndex << 1; // pre-multiply by 2 for simpler indexing
+    positiveOverflowLimit = _int64OverflowLimits[tableIndex];
+    if (positiveOverflowLimit == 0) {
+      positiveOverflowLimit = _initInt64OverflowLimits(tableIndex, multiplier);
+    }
+    negativeOverflowLimit = _int64OverflowLimits[tableIndex + 1];
+    int blockEnd = start + blockSize;
+    do {
+      _Smi smi = _parseBlock(source, radix, start, blockEnd);
+      if (smi == null) {
+        return _throwFormatException(onError, source, start, radix, null);
+      }
+      if (result >= positiveOverflowLimit) {
+        if ((result > positiveOverflowLimit) ||
+            (smi > _int64OverflowLimits[tableIndex + 2])) {
+          // Although the unsigned overflow limits do not depend on the
+          // platform, the multiplier and block size, which are used to
+          // compute it, do.
+          int X = is64Bit ? 1 : 0;
+          if (allowU64 &&
+              !(result >= _int64UnsignedOverflowLimits[X] &&
+                  (result > _int64UnsignedOverflowLimits[X] ||
+                      smi > _int64UnsignedSmiOverflowLimits[X])) &&
+              blockEnd + blockSize > end) {
+            return (result * multiplier) + smi;
+          }
+          return _throwFormatException(onError, source, null, radix,
+              "Positive input exceeds the limit of integer");
+        }
+      } else if (result <= negativeOverflowLimit) {
+        if ((result < negativeOverflowLimit) ||
+            (smi > _int64OverflowLimits[tableIndex + 3])) {
+          return _throwFormatException(onError, source, null, radix,
+              "Negative input exceeds the limit of integer");
+        }
+      }
+      result = (result * multiplier) + (sign * smi);
+      start = blockEnd;
+      blockEnd = start + blockSize;
+    } while (blockEnd <= end);
+    return result;
+  }
+
+  // Parse block of digits into a Smi.
+  static _Smi _parseBlock(String source, int radix, int start, int end) {
+    _Smi result = 0;
+    if (radix <= 10) {
+      for (int i = start; i < end; i++) {
+        int digit = source.codeUnitAt(i) ^ 0x30;
+        if (digit >= radix) return null;
+        result = radix * result + digit;
+      }
+    } else {
+      for (int i = start; i < end; i++) {
+        int char = source.codeUnitAt(i);
+        int digit = char ^ 0x30;
+        if (digit > 9) {
+          digit = (char | 0x20) - (0x61 - 10);
+          if (digit < 10 || digit >= radix) return null;
+        }
+        result = radix * result + digit;
+      }
+    }
+    return result;
+  }
+
+  // For each radix, 2-36, how many digits are guaranteed to fit in a smi,
+  // and magnitude of such a block (radix ** digit-count).
+  // 32-bit limit/multiplier at (radix - 2)*4, 64-bit limit at (radix-2)*4+2
+  static const _PARSE_LIMITS = const [
+    30, 1073741824, 62, 4611686018427387904, // radix: 2
+    18, 387420489, 39, 4052555153018976267,
+    15, 1073741824, 30, 1152921504606846976,
+    12, 244140625, 26, 1490116119384765625, //  radix: 5
+    11, 362797056, 23, 789730223053602816,
+    10, 282475249, 22, 3909821048582988049,
+    10, 1073741824, 20, 1152921504606846976,
+    9, 387420489, 19, 1350851717672992089,
+    9, 1000000000, 18, 1000000000000000000, //  radix: 10
+    8, 214358881, 17, 505447028499293771,
+    8, 429981696, 17, 2218611106740436992,
+    8, 815730721, 16, 665416609183179841,
+    7, 105413504, 16, 2177953337809371136,
+    7, 170859375, 15, 437893890380859375, //    radix: 15
+    7, 268435456, 15, 1152921504606846976,
+    7, 410338673, 15, 2862423051509815793,
+    7, 612220032, 14, 374813367582081024,
+    7, 893871739, 14, 799006685782884121,
+    6, 64000000, 14, 1638400000000000000, //    radix: 20
+    6, 85766121, 14, 3243919932521508681,
+    6, 113379904, 13, 282810057883082752,
+    6, 148035889, 13, 504036361936467383,
+    6, 191102976, 13, 876488338465357824,
+    6, 244140625, 13, 1490116119384765625, //   radix: 25
+    6, 308915776, 13, 2481152873203736576,
+    6, 387420489, 13, 4052555153018976267,
+    6, 481890304, 12, 232218265089212416,
+    6, 594823321, 12, 353814783205469041,
+    6, 729000000, 12, 531441000000000000, //    radix: 30
+    6, 887503681, 12, 787662783788549761,
+    6, 1073741824, 12, 1152921504606846976,
+    5, 39135393, 12, 1667889514952984961,
+    5, 45435424, 12, 2386420683693101056,
+    5, 52521875, 12, 3379220508056640625, //    radix: 35
+    5, 60466176, 11, 131621703842267136,
+  ];
+
+  static const _maxInt64 = 0x7fffffffffffffff;
+  static const _minInt64 = -0x8000000000000000;
+
+  static const _int64UnsignedOverflowLimits = const [0xfffffffff, 0xf];
+  static const _int64UnsignedSmiOverflowLimits = const [
+    0xfffffff,
+    0xfffffffffffffff
+  ];
+
+  /// Calculation of the expression
+  ///
+  ///   result = (result * multiplier) + (sign * smi)
+  ///
+  /// in `_parseRadix()` may overflow 64-bit integers. In such case,
+  /// `int.parse()` should stop with an error.
+  ///
+  /// This table is lazily filled with int64 overflow limits for result and smi.
+  /// For each multiplier from `_PARSE_LIMITS[tableIndex + 1]` this table
+  /// contains
+  ///
+  /// * `[tableIndex*2]` = positive limit for result
+  /// * `[tableIndex*2 + 1]` = negative limit for result
+  /// * `[tableIndex*2 + 2]` = limit for smi if result is exactly at positive limit
+  /// * `[tableIndex*2 + 3]` = limit for smi if result is exactly at negative limit
+  static final Int64List _int64OverflowLimits =
+      new Int64List(_PARSE_LIMITS.length * 2);
+
+  static int _initInt64OverflowLimits(int tableIndex, int multiplier) {
+    _int64OverflowLimits[tableIndex] = _maxInt64 ~/ multiplier;
+    _int64OverflowLimits[tableIndex + 1] = _minInt64 ~/ multiplier;
+    _int64OverflowLimits[tableIndex + 2] = _maxInt64.remainder(multiplier);
+    _int64OverflowLimits[tableIndex + 3] = -(_minInt64.remainder(multiplier));
+    return _int64OverflowLimits[tableIndex];
+  }
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/internal_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/internal_patch.dart
new file mode 100644
index 0000000..6e6d5be
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/internal_patch.dart
@@ -0,0 +1,126 @@
+// 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
+
+/// Note: the VM concatenates all patch files into a single patch file. This
+/// file is the first patch in "dart:_internal" which contains all the imports
+/// used by patches of that library. We plan to change this when we have a
+/// shared front end and simply use parts.
+
+import "dart:core" hide Symbol;
+
+import "dart:typed_data" show Int32List;
+
+/// These are the additional parts of this patch library:
+// part "class_id_fasta.dart";
+// part "print_patch.dart";
+// part "symbol_patch.dart";
+
+@patch
+List<T> makeListFixedLength<T>(List<T> growableList)
+    native "Internal_makeListFixedLength";
+
+@patch
+List<T> makeFixedListUnmodifiable<T>(List<T> fixedLengthList)
+    native "Internal_makeFixedListUnmodifiable";
+
+@patch
+Object extractTypeArguments<T>(T instance, Function extract)
+    native "Internal_extractTypeArguments";
+
+class VMLibraryHooks {
+  // Example: "dart:isolate _Timer._factory"
+  static var timerFactory;
+
+  // Example: "dart:io _EventHandler._sendData"
+  static var eventHandlerSendData;
+
+  // A nullary closure that answers the current clock value in milliseconds.
+  // Example: "dart:io _EventHandler._timerMillisecondClock"
+  static var timerMillisecondClock;
+
+  // Implementation of Resource.readAsBytes.
+  static var resourceReadAsBytes;
+
+  // Implementation of package root/map provision.
+  static var packageRootString;
+  static var packageConfigString;
+  static var packageRootUriFuture;
+  static var packageConfigUriFuture;
+  static var resolvePackageUriFuture;
+
+  static var _computeScriptUri;
+  static var _cachedScript;
+  static set platformScript(var f) {
+    _computeScriptUri = f;
+    _cachedScript = null;
+  }
+
+  static get platformScript {
+    if (_cachedScript == null && _computeScriptUri != null) {
+      _cachedScript = _computeScriptUri();
+    }
+    return _cachedScript;
+  }
+}
+
+final bool is64Bit = _inquireIs64Bit();
+
+bool _inquireIs64Bit() native "Internal_inquireIs64Bit";
+
+@pragma("vm:entry-point", "call")
+@pragma("vm:exact-result-type", bool)
+@pragma("vm:prefer-inline")
+bool _classRangeCheck(int cid, int lowerLimit, int upperLimit) {
+  return cid >= lowerLimit && cid <= upperLimit;
+}
+
+// Utility class now only used by the VM.
+class Lists {
+  @pragma("vm:prefer-inline")
+  static void copy(List src, int srcStart, List dst, int dstStart, int count) {
+    if (srcStart < dstStart) {
+      for (int i = srcStart + count - 1, j = dstStart + count - 1;
+          i >= srcStart;
+          i--, j--) {
+        dst[j] = src[i];
+      }
+    } else {
+      for (int i = srcStart, j = dstStart; i < srcStart + count; i++, j++) {
+        dst[j] = src[i];
+      }
+    }
+  }
+}
+
+// Prepend the parent type arguments (maybe null) of length 'parentLen' to the
+// function type arguments (may be null). The result is null if both input
+// vectors are null or is a newly allocated and canonicalized vector of length
+// 'totalLen'.
+@pragma("vm:entry-point", "call")
+_prependTypeArguments(functionTypeArguments, parentTypeArguments, parentLen,
+    totalLen) native "Internal_prependTypeArguments";
+
+// Check that a set of type arguments satisfy the type parameter bounds on a
+// closure.
+@pragma("vm:entry-point", "call")
+_boundsCheckForPartialInstantiation(closure, typeArgs)
+    native "Internal_boundsCheckForPartialInstantiation";
+
+// Called by IRRegExpMacroAssembler::GrowStack.
+Int32List _growRegExpStack(Int32List stack) {
+  final newStack = new Int32List(stack.length * 2);
+  for (int i = 0; i < stack.length; i++) {
+    newStack[i] = stack[i];
+  }
+  return newStack;
+}
+
+// This function can be used to skip implicit or explicit checked down casts in
+// the parts of the core library implementation where we know by construction the
+// type of a value.
+//
+// Important: this is unsafe and must be used with care.
+T unsafeCast<T>(Object v) native "Internal_unsafeCast";
diff --git a/sdk_nnbd/lib/_internal/vm/lib/invocation_mirror_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/invocation_mirror_patch.dart
new file mode 100644
index 0000000..4472d2c
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/invocation_mirror_patch.dart
@@ -0,0 +1,204 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+// NOTE: When making changes to this class, please also update
+// `VmTarget.instantiateInvocation` and `VmTarget._invocationType` in
+// `pkg/kernel/lib/target/vm.dart`.
+class _InvocationMirror implements Invocation {
+  // Constants describing the invocation kind.
+  // _FIELD cannot be generated by regular invocation mirrors.
+  static const int _METHOD = 0;
+  static const int _GETTER = 1;
+  static const int _SETTER = 2;
+  static const int _FIELD = 3;
+  static const int _LOCAL_VAR = 4;
+  static const int _KIND_SHIFT = 0;
+  static const int _KIND_BITS = 3;
+  static const int _KIND_MASK = (1 << _KIND_BITS) - 1;
+
+  // These values, except _DYNAMIC and _SUPER, are only used when throwing
+  // NoSuchMethodError for compile-time resolution failures.
+  static const int _DYNAMIC = 0;
+  static const int _SUPER = 1;
+  static const int _STATIC = 2;
+  static const int _CONSTRUCTOR = 3;
+  static const int _TOP_LEVEL = 4;
+  static const int _LEVEL_SHIFT = _KIND_BITS;
+  static const int _LEVEL_BITS = 3;
+  static const int _LEVEL_MASK = (1 << _LEVEL_BITS) - 1;
+
+  // ArgumentsDescriptor layout. Keep in sync with enum in dart_entry.h.
+  static const int _TYPE_ARGS_LEN = 0;
+  static const int _COUNT = 1;
+  static const int _POSITIONAL_COUNT = 2;
+  static const int _FIRST_NAMED_ENTRY = 3;
+
+  // Internal representation of the invocation mirror.
+  String _functionName;
+  List _argumentsDescriptor;
+  List _arguments;
+  bool _isSuperInvocation;
+  int _delayedTypeArgumentsLen;
+
+  // External representation of the invocation mirror; populated on demand.
+  Symbol _memberName;
+  int _type;
+  List<Type> _typeArguments;
+  List _positionalArguments;
+  Map<Symbol, dynamic> _namedArguments;
+
+  _InvocationMirror._withType(this._memberName, this._type, this._typeArguments,
+      this._positionalArguments, this._namedArguments) {
+    _typeArguments ??= const <Type>[];
+    _positionalArguments ??= const [];
+    _namedArguments ??= const {};
+  }
+
+  void _setMemberNameAndType() {
+    _type ??= 0;
+    if (_functionName.startsWith("get:")) {
+      _type |= _GETTER;
+      _memberName = new internal.Symbol.unvalidated(_functionName.substring(4));
+    } else if (_functionName.startsWith("set:")) {
+      _type |= _SETTER;
+      _memberName =
+          new internal.Symbol.unvalidated(_functionName.substring(4) + "=");
+    } else {
+      _type |=
+          _isSuperInvocation ? (_SUPER << _LEVEL_SHIFT) | _METHOD : _METHOD;
+      _memberName = new internal.Symbol.unvalidated(_functionName);
+    }
+  }
+
+  Symbol get memberName {
+    if (_memberName == null) {
+      _setMemberNameAndType();
+    }
+    return _memberName;
+  }
+
+  int get _typeArgsLen {
+    int typeArgsLen = _argumentsDescriptor[_TYPE_ARGS_LEN];
+    return typeArgsLen == 0 ? _delayedTypeArgumentsLen : typeArgsLen;
+  }
+
+  List<Type> get typeArguments {
+    if (_typeArguments == null) {
+      if (_typeArgsLen == 0) {
+        return _typeArguments = const <Type>[];
+      }
+      // A TypeArguments object does not have a corresponding Dart class and
+      // cannot be accessed as an array in Dart. Therefore, we need a native
+      // call to unpack the individual types into a list.
+      _typeArguments = _unpackTypeArguments(_arguments[0], _typeArgsLen);
+    }
+    return _typeArguments;
+  }
+
+  // Unpack the given TypeArguments object into a new list of individual types.
+  static List<Type> _unpackTypeArguments(typeArguments, int numTypeArguments)
+      native "InvocationMirror_unpackTypeArguments";
+
+  List get positionalArguments {
+    if (_positionalArguments == null) {
+      // The argument descriptor counts the receiver, but not the type arguments
+      // as positional arguments.
+      int numPositionalArguments = _argumentsDescriptor[_POSITIONAL_COUNT] - 1;
+      if (numPositionalArguments == 0) {
+        return _positionalArguments = const [];
+      }
+      // Exclude receiver and type args in the returned list.
+      int receiverIndex = _typeArgsLen > 0 ? 1 : 0;
+      _positionalArguments = new _ImmutableList._from(
+          _arguments, receiverIndex + 1, numPositionalArguments);
+    }
+    return _positionalArguments;
+  }
+
+  Map<Symbol, dynamic> get namedArguments {
+    if (_namedArguments == null) {
+      int numArguments = _argumentsDescriptor[_COUNT] - 1; // Exclude receiver.
+      int numPositionalArguments = _argumentsDescriptor[_POSITIONAL_COUNT] - 1;
+      int numNamedArguments = numArguments - numPositionalArguments;
+      if (numNamedArguments == 0) {
+        return _namedArguments = const {};
+      }
+      int receiverIndex = _typeArgsLen > 0 ? 1 : 0;
+      _namedArguments = new Map<Symbol, dynamic>();
+      for (int i = 0; i < numNamedArguments; i++) {
+        int namedEntryIndex = _FIRST_NAMED_ENTRY + 2 * i;
+        String arg_name = _argumentsDescriptor[namedEntryIndex];
+        var arg_value = _arguments[
+            receiverIndex + _argumentsDescriptor[namedEntryIndex + 1]];
+        _namedArguments[new internal.Symbol.unvalidated(arg_name)] = arg_value;
+      }
+      _namedArguments = new Map.unmodifiable(_namedArguments);
+    }
+    return _namedArguments;
+  }
+
+  bool get isMethod {
+    if (_type == null) {
+      _setMemberNameAndType();
+    }
+    return (_type & _KIND_MASK) == _METHOD;
+  }
+
+  bool get isAccessor {
+    if (_type == null) {
+      _setMemberNameAndType();
+    }
+    return (_type & _KIND_MASK) != _METHOD;
+  }
+
+  bool get isGetter {
+    if (_type == null) {
+      _setMemberNameAndType();
+    }
+    return (_type & _KIND_MASK) == _GETTER;
+  }
+
+  bool get isSetter {
+    if (_type == null) {
+      _setMemberNameAndType();
+    }
+    return (_type & _KIND_MASK) == _SETTER;
+  }
+
+  _InvocationMirror(this._functionName, this._argumentsDescriptor,
+      this._arguments, this._isSuperInvocation, this._type,
+      [this._delayedTypeArgumentsLen = 0]);
+
+  _InvocationMirror._withoutType(this._functionName, this._typeArguments,
+      this._positionalArguments, this._namedArguments, this._isSuperInvocation,
+      [this._delayedTypeArgumentsLen = 0]);
+
+  @pragma("vm:entry-point", "call")
+  static _allocateInvocationMirror(String functionName,
+      List argumentsDescriptor, List arguments, bool isSuperInvocation,
+      [int type = null]) {
+    return new _InvocationMirror(
+        functionName, argumentsDescriptor, arguments, isSuperInvocation, type);
+  }
+
+  // This factory is used when creating an `Invocation` for a closure call which
+  // may have delayed type arguments. In that case, the arguments descriptor will
+  // indicate 0 type arguments, but the actual number of type arguments are
+  // passed in `delayedTypeArgumentsLen`. If any type arguments are available,
+  // the type arguments vector will be the first entry in `arguments`.
+  @pragma("vm:entry-point", "call")
+  static _allocateInvocationMirrorForClosure(
+      String functionName,
+      List argumentsDescriptor,
+      List arguments,
+      int type,
+      int delayedTypeArgumentsLen) {
+    return new _InvocationMirror(functionName, argumentsDescriptor, arguments,
+        false, type, delayedTypeArgumentsLen);
+  }
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/isolate_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/isolate_patch.dart
new file mode 100644
index 0000000..ec4bcf1
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/isolate_patch.dart
@@ -0,0 +1,710 @@
+// 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.
+
+// @dart = 2.5
+
+/// Note: the VM concatenates all patch files into a single patch file. This
+/// file is the first patch in "dart:isolate" which contains all the imports
+/// used by patches of that library. We plan to change this when we have a
+/// shared front end and simply use parts.
+
+import "dart:_internal" show ClassID, VMLibraryHooks, patch;
+
+import "dart:async"
+    show Completer, Future, Stream, StreamController, StreamSubscription, Timer;
+
+import "dart:collection" show HashMap;
+import "dart:typed_data" show ByteBuffer, TypedData, Uint8List;
+
+/// These are the additional parts of this patch library:
+// part "timer_impl.dart";
+
+@patch
+class ReceivePort {
+  @patch
+  factory ReceivePort() => new _ReceivePortImpl();
+
+  @patch
+  factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort) {
+    return new _ReceivePortImpl.fromRawReceivePort(rawPort);
+  }
+}
+
+@patch
+class Capability {
+  @patch
+  factory Capability() => new _CapabilityImpl();
+}
+
+@pragma("vm:entry-point")
+class _CapabilityImpl implements Capability {
+  factory _CapabilityImpl() native "CapabilityImpl_factory";
+
+  bool operator ==(var other) {
+    return (other is _CapabilityImpl) && _equals(other);
+  }
+
+  int get hashCode {
+    return _get_hashcode();
+  }
+
+  _equals(other) native "CapabilityImpl_equals";
+  _get_hashcode() native "CapabilityImpl_get_hashcode";
+}
+
+@patch
+class RawReceivePort {
+  /**
+   * Opens a long-lived port for receiving messages.
+   *
+   * A [RawReceivePort] is low level and does not work with [Zone]s. It
+   * can not be paused. The data-handler must be set before the first
+   * event is received.
+   */
+  @patch
+  factory RawReceivePort([Function handler]) {
+    _RawReceivePortImpl result = new _RawReceivePortImpl();
+    result.handler = handler;
+    return result;
+  }
+}
+
+class _ReceivePortImpl extends Stream implements ReceivePort {
+  _ReceivePortImpl() : this.fromRawReceivePort(new RawReceivePort());
+
+  _ReceivePortImpl.fromRawReceivePort(this._rawPort) {
+    _controller = new StreamController(onCancel: close, sync: true);
+    _rawPort.handler = _controller.add;
+  }
+
+  SendPort get sendPort {
+    return _rawPort.sendPort;
+  }
+
+  StreamSubscription listen(void onData(var message),
+      {Function onError, void onDone(), bool cancelOnError}) {
+    return _controller.stream.listen(onData,
+        onError: onError, onDone: onDone, cancelOnError: cancelOnError);
+  }
+
+  close() {
+    _rawPort.close();
+    _controller.close();
+  }
+
+  final RawReceivePort _rawPort;
+  StreamController _controller;
+}
+
+typedef void _ImmediateCallback();
+
+/// The callback that has been registered through `scheduleImmediate`.
+_ImmediateCallback _pendingImmediateCallback;
+
+/// The closure that should be used as scheduleImmediateClosure, when the VM
+/// is responsible for the event loop.
+void _isolateScheduleImmediate(void callback()) {
+  assert((_pendingImmediateCallback == null) ||
+      (_pendingImmediateCallback == callback));
+  _pendingImmediateCallback = callback;
+}
+
+@pragma("vm:entry-point", "call")
+void _runPendingImmediateCallback() {
+  if (_pendingImmediateCallback != null) {
+    var callback = _pendingImmediateCallback;
+    _pendingImmediateCallback = null;
+    callback();
+  }
+}
+
+_ImmediateCallback _removePendingImmediateCallback() {
+  var callback = _pendingImmediateCallback;
+  _pendingImmediateCallback = null;
+  return callback;
+}
+
+/// The embedder can execute this function to get hold of
+/// [_isolateScheduleImmediate] above.
+@pragma("vm:entry-point", "call")
+Function _getIsolateScheduleImmediateClosure() {
+  return _isolateScheduleImmediate;
+}
+
+@pragma("vm:entry-point")
+class _RawReceivePortImpl implements RawReceivePort {
+  factory _RawReceivePortImpl() native "RawReceivePortImpl_factory";
+
+  close() {
+    // Close the port and remove it from the handler map.
+    _handlerMap.remove(this._closeInternal());
+  }
+
+  SendPort get sendPort {
+    return _get_sendport();
+  }
+
+  bool operator ==(var other) {
+    return (other is _RawReceivePortImpl) &&
+        (this._get_id() == other._get_id());
+  }
+
+  int get hashCode {
+    return sendPort.hashCode;
+  }
+
+  /**** Internal implementation details ****/
+  _get_id() native "RawReceivePortImpl_get_id";
+  _get_sendport() native "RawReceivePortImpl_get_sendport";
+
+  // Called from the VM to retrieve the handler for a message.
+  @pragma("vm:entry-point", "call")
+  static _lookupHandler(int id) {
+    var result = _handlerMap[id];
+    return result;
+  }
+
+  // Called from the VM to dispatch to the handler.
+  @pragma("vm:entry-point", "call")
+  static void _handleMessage(Function handler, var message) {
+    // TODO(floitsch): this relies on the fact that any exception aborts the
+    // VM. Once we have non-fatal global exceptions we need to catch errors
+    // so that we can run the immediate callbacks.
+    handler(message);
+    _runPendingImmediateCallback();
+  }
+
+  // Call into the VM to close the VM maintained mappings.
+  _closeInternal() native "RawReceivePortImpl_closeInternal";
+
+  void set handler(Function value) {
+    _handlerMap[this._get_id()] = value;
+  }
+
+  // TODO(iposva): Ideally keep this map in the VM.
+  // id to handler mapping.
+  static _initHandlerMap() {
+    // TODO(18511): Workaround bad CheckSmi hoisting.
+    var tempMap = new HashMap();
+    // Collect feedback that not all keys are Smis.
+    tempMap["."] = 1;
+    tempMap["."] = 2;
+
+    return new HashMap();
+  }
+
+  static final Map _handlerMap = _initHandlerMap();
+}
+
+@pragma("vm:entry-point")
+class _SendPortImpl implements SendPort {
+  factory _SendPortImpl._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  /*--- public interface ---*/
+  @pragma("vm:entry-point", "call")
+  void send(var message) {
+    _sendInternal(message);
+  }
+
+  bool operator ==(var other) {
+    return (other is _SendPortImpl) && (this._get_id() == other._get_id());
+  }
+
+  int get hashCode {
+    return _get_hashcode();
+  }
+
+  /*--- private implementation ---*/
+  _get_id() native "SendPortImpl_get_id";
+  _get_hashcode() native "SendPortImpl_get_hashcode";
+
+  // Forward the implementation of sending messages to the VM.
+  void _sendInternal(var message) native "SendPortImpl_sendInternal_";
+}
+
+typedef _NullaryFunction();
+typedef _UnaryFunction(Null args);
+typedef _BinaryFunction(Null args, Null message);
+
+/**
+ * Takes the real entry point as argument and invokes it with the
+ * initial message.  Defers execution of the entry point until the
+ * isolate is in the message loop.
+ */
+@pragma("vm:entry-point", "call")
+void _startMainIsolate(Function entryPoint, List<String> args) {
+  _startIsolate(
+      null, // no parent port
+      entryPoint,
+      args,
+      null, // no message
+      true, // isSpawnUri
+      null, // no control port
+      null); // no capabilities
+}
+
+/**
+ * Returns the _startMainIsolate function. This closurization allows embedders
+ * to setup trampolines to the main function. This workaround can be removed
+ * once support for @pragma("vm:entry_point", "get") as documented in
+ * https://github.com/dart-lang/sdk/issues/35720 lands.
+ */
+@pragma("vm:entry-point", "call")
+Function _getStartMainIsolateFunction() {
+  return _startMainIsolate;
+}
+
+/**
+ * Takes the real entry point as argument and invokes it with the initial
+ * message.
+ */
+@pragma("vm:entry-point", "call")
+void _startIsolate(
+    SendPort parentPort,
+    Function entryPoint,
+    List<String> args,
+    var message,
+    bool isSpawnUri,
+    RawReceivePort controlPort,
+    List capabilities) {
+  // The control port (aka the main isolate port) does not handle any messages.
+  if (controlPort != null) {
+    controlPort.handler = (_) {}; // Nobody home on the control port.
+  }
+
+  if (parentPort != null) {
+    // Build a message to our parent isolate providing access to the
+    // current isolate's control port and capabilities.
+    //
+    // TODO(floitsch): Send an error message if we can't find the entry point.
+    var readyMessage = new List(2);
+    readyMessage[0] = controlPort.sendPort;
+    readyMessage[1] = capabilities;
+
+    // Out of an excess of paranoia we clear the capabilities from the
+    // stack.  Not really necessary.
+    capabilities = null;
+    parentPort.send(readyMessage);
+  }
+  assert(capabilities == null);
+
+  // Delay all user code handling to the next run of the message loop. This
+  // allows us to intercept certain conditions in the event dispatch, such as
+  // starting in paused state.
+  RawReceivePort port = new RawReceivePort();
+  port.handler = (_) {
+    port.close();
+
+    if (isSpawnUri) {
+      if (entryPoint is _BinaryFunction) {
+        (entryPoint as dynamic)(args, message);
+      } else if (entryPoint is _UnaryFunction) {
+        (entryPoint as dynamic)(args);
+      } else {
+        entryPoint();
+      }
+    } else {
+      entryPoint(message);
+    }
+  };
+  // Make sure the message handler is triggered.
+  port.sendPort.send(null);
+}
+
+@patch
+class Isolate {
+  static final _currentIsolate = _getCurrentIsolate();
+  static final _rootUri = _getCurrentRootUri();
+
+  @patch
+  static Isolate get current => _currentIsolate;
+
+  @patch
+  String get debugName => _getDebugName(controlPort);
+
+  @patch
+  static Future<Uri> get packageRoot {
+    var hook = VMLibraryHooks.packageRootUriFuture;
+    if (hook == null) {
+      throw new UnsupportedError("Isolate.packageRoot");
+    }
+    return hook();
+  }
+
+  @patch
+  static Future<Uri> get packageConfig {
+    var hook = VMLibraryHooks.packageConfigUriFuture;
+    if (hook == null) {
+      throw new UnsupportedError("Isolate.packageConfig");
+    }
+    return hook();
+  }
+
+  @patch
+  static Future<Uri> resolvePackageUri(Uri packageUri) {
+    var hook = VMLibraryHooks.resolvePackageUriFuture;
+    if (hook == null) {
+      throw new UnsupportedError("Isolate.resolvePackageUri");
+    }
+    return hook(packageUri);
+  }
+
+  static bool _packageSupported() =>
+      (VMLibraryHooks.packageRootUriFuture != null) &&
+      (VMLibraryHooks.packageConfigUriFuture != null) &&
+      (VMLibraryHooks.resolvePackageUriFuture != null);
+
+  @patch
+  static Future<Isolate> spawn<T>(void entryPoint(T message), T message,
+      {bool paused: false,
+      bool errorsAreFatal,
+      SendPort onExit,
+      SendPort onError,
+      String debugName}) async {
+    // `paused` isn't handled yet.
+    RawReceivePort readyPort;
+    try {
+      // Check for the type of `entryPoint` on the spawning isolate to make
+      // error-handling easier.
+      if (entryPoint is! _UnaryFunction) {
+        throw new ArgumentError(entryPoint);
+      }
+      // The VM will invoke [_startIsolate] with entryPoint as argument.
+      readyPort = new RawReceivePort();
+
+      // We do not inherit the package config settings from the parent isolate,
+      // instead we use the values that were set on the command line.
+      var packageConfig = VMLibraryHooks.packageConfigString;
+      var script = VMLibraryHooks.platformScript;
+      if (script == null) {
+        // We do not have enough information to support spawning the new
+        // isolate.
+        throw new UnsupportedError("Isolate.spawn");
+      }
+      if (script.scheme == "package") {
+        script = await Isolate.resolvePackageUri(script);
+      }
+
+      _spawnFunction(
+          readyPort.sendPort,
+          script.toString(),
+          entryPoint,
+          message,
+          paused,
+          errorsAreFatal,
+          onExit,
+          onError,
+          null,
+          packageConfig,
+          debugName);
+      return await _spawnCommon(readyPort);
+    } catch (e, st) {
+      if (readyPort != null) {
+        readyPort.close();
+      }
+      return await new Future<Isolate>.error(e, st);
+    }
+  }
+
+  @patch
+  static Future<Isolate> spawnUri(Uri uri, List<String> args, var message,
+      {bool paused: false,
+      SendPort onExit,
+      SendPort onError,
+      bool errorsAreFatal,
+      bool checked,
+      Map<String, String> environment,
+      Uri packageRoot,
+      Uri packageConfig,
+      bool automaticPackageResolution: false,
+      String debugName}) async {
+    RawReceivePort readyPort;
+    if (environment != null) {
+      throw new UnimplementedError("environment");
+    }
+
+    // Verify that no mutually exclusive arguments have been passed.
+    if (automaticPackageResolution) {
+      if (packageRoot != null) {
+        throw new ArgumentError("Cannot simultaneously request "
+            "automaticPackageResolution and specify a"
+            "packageRoot.");
+      }
+      if (packageConfig != null) {
+        throw new ArgumentError("Cannot simultaneously request "
+            "automaticPackageResolution and specify a"
+            "packageConfig.");
+      }
+    } else {
+      if ((packageRoot != null) && (packageConfig != null)) {
+        throw new ArgumentError("Cannot simultaneously specify a "
+            "packageRoot and a packageConfig.");
+      }
+    }
+    try {
+      // Resolve the uri against the current isolate's root Uri first.
+      var spawnedUri = _rootUri.resolveUri(uri);
+
+      // Inherit this isolate's package resolution setup if not overridden.
+      if (!automaticPackageResolution &&
+          (packageRoot == null) &&
+          (packageConfig == null)) {
+        if (Isolate._packageSupported()) {
+          packageRoot = await Isolate.packageRoot;
+          packageConfig = await Isolate.packageConfig;
+        }
+      }
+
+      // Ensure to resolve package: URIs being handed in as parameters.
+      if (packageRoot != null) {
+        // `packages/` directory is no longer supported. Force it null.
+        // TODO(mfairhurst) Should this throw an exception?
+        packageRoot = null;
+      } else if (packageConfig != null) {
+        // Avoid calling resolvePackageUri if not strictly necessary in case
+        // the API is not supported.
+        if (packageConfig.scheme == "package") {
+          packageConfig = await Isolate.resolvePackageUri(packageConfig);
+        }
+      }
+
+      // The VM will invoke [_startIsolate] and not `main`.
+      readyPort = new RawReceivePort();
+      var packageRootString = packageRoot?.toString();
+      var packageConfigString = packageConfig?.toString();
+
+      _spawnUri(
+          readyPort.sendPort,
+          spawnedUri.toString(),
+          args,
+          message,
+          paused,
+          onExit,
+          onError,
+          errorsAreFatal,
+          checked,
+          null,
+          /* environment */
+          packageRootString,
+          packageConfigString,
+          debugName);
+      return await _spawnCommon(readyPort);
+    } catch (e) {
+      if (readyPort != null) {
+        readyPort.close();
+      }
+      rethrow;
+    }
+  }
+
+  static Future<Isolate> _spawnCommon(RawReceivePort readyPort) {
+    Completer completer = new Completer<Isolate>.sync();
+    readyPort.handler = (readyMessage) {
+      readyPort.close();
+      if (readyMessage is List && readyMessage.length == 2) {
+        SendPort controlPort = readyMessage[0];
+        List capabilities = readyMessage[1];
+        completer.complete(new Isolate(controlPort,
+            pauseCapability: capabilities[0],
+            terminateCapability: capabilities[1]));
+      } else if (readyMessage is String) {
+        // We encountered an error while starting the new isolate.
+        completer.completeError(new IsolateSpawnException(
+            'Unable to spawn isolate: ${readyMessage}'));
+      } else {
+        // This shouldn't happen.
+        completer.completeError(new IsolateSpawnException(
+            "Internal error: unexpected format for ready message: "
+            "'${readyMessage}'"));
+      }
+    };
+    return completer.future;
+  }
+
+  // TODO(iposva): Cleanup to have only one definition.
+  // These values need to be kept in sync with the class IsolateMessageHandler
+  // in vm/isolate.cc.
+  static const _PAUSE = 1;
+  static const _RESUME = 2;
+  static const _PING = 3;
+  static const _KILL = 4;
+  static const _ADD_EXIT = 5;
+  static const _DEL_EXIT = 6;
+  static const _ADD_ERROR = 7;
+  static const _DEL_ERROR = 8;
+  static const _ERROR_FATAL = 9;
+
+  static void _spawnFunction(
+      SendPort readyPort,
+      String uri,
+      Function topLevelFunction,
+      var message,
+      bool paused,
+      bool errorsAreFatal,
+      SendPort onExit,
+      SendPort onError,
+      String packageRoot,
+      String packageConfig,
+      String debugName) native "Isolate_spawnFunction";
+
+  static void _spawnUri(
+      SendPort readyPort,
+      String uri,
+      List<String> args,
+      var message,
+      bool paused,
+      SendPort onExit,
+      SendPort onError,
+      bool errorsAreFatal,
+      bool checked,
+      List environment,
+      String packageRoot,
+      String packageConfig,
+      String debugName) native "Isolate_spawnUri";
+
+  static void _sendOOB(port, msg) native "Isolate_sendOOB";
+
+  static String _getDebugName(SendPort controlPort)
+      native "Isolate_getDebugName";
+
+  @patch
+  void _pause(Capability resumeCapability) {
+    var msg = new List(4)
+      ..[0] = 0 // Make room for OOB message type.
+      ..[1] = _PAUSE
+      ..[2] = pauseCapability
+      ..[3] = resumeCapability;
+    _sendOOB(controlPort, msg);
+  }
+
+  @patch
+  void resume(Capability resumeCapability) {
+    var msg = new List(4)
+      ..[0] = 0 // Make room for OOB message type.
+      ..[1] = _RESUME
+      ..[2] = pauseCapability
+      ..[3] = resumeCapability;
+    _sendOOB(controlPort, msg);
+  }
+
+  @patch
+  void addOnExitListener(SendPort responsePort, {Object response}) {
+    var msg = new List(4)
+      ..[0] = 0 // Make room for OOB message type.
+      ..[1] = _ADD_EXIT
+      ..[2] = responsePort
+      ..[3] = response;
+    _sendOOB(controlPort, msg);
+  }
+
+  @patch
+  void removeOnExitListener(SendPort responsePort) {
+    var msg = new List(3)
+      ..[0] = 0 // Make room for OOB message type.
+      ..[1] = _DEL_EXIT
+      ..[2] = responsePort;
+    _sendOOB(controlPort, msg);
+  }
+
+  @patch
+  void setErrorsFatal(bool errorsAreFatal) {
+    var msg = new List(4)
+      ..[0] = 0 // Make room for OOB message type.
+      ..[1] = _ERROR_FATAL
+      ..[2] = terminateCapability
+      ..[3] = errorsAreFatal;
+    _sendOOB(controlPort, msg);
+  }
+
+  @patch
+  void kill({int priority: beforeNextEvent}) {
+    var msg = new List(4)
+      ..[0] = 0 // Make room for OOB message type.
+      ..[1] = _KILL
+      ..[2] = terminateCapability
+      ..[3] = priority;
+    _sendOOB(controlPort, msg);
+  }
+
+  @patch
+  void ping(SendPort responsePort, {Object response, int priority: immediate}) {
+    var msg = new List(5)
+      ..[0] = 0 // Make room for OOM message type.
+      ..[1] = _PING
+      ..[2] = responsePort
+      ..[3] = priority
+      ..[4] = response;
+    _sendOOB(controlPort, msg);
+  }
+
+  @patch
+  void addErrorListener(SendPort port) {
+    var msg = new List(3)
+      ..[0] = 0 // Make room for OOB message type.
+      ..[1] = _ADD_ERROR
+      ..[2] = port;
+    _sendOOB(controlPort, msg);
+  }
+
+  @patch
+  void removeErrorListener(SendPort port) {
+    var msg = new List(3)
+      ..[0] = 0 // Make room for OOB message type.
+      ..[1] = _DEL_ERROR
+      ..[2] = port;
+    _sendOOB(controlPort, msg);
+  }
+
+  static Isolate _getCurrentIsolate() {
+    List portAndCapabilities = _getPortAndCapabilitiesOfCurrentIsolate();
+    return new Isolate(portAndCapabilities[0],
+        pauseCapability: portAndCapabilities[1],
+        terminateCapability: portAndCapabilities[2]);
+  }
+
+  static List _getPortAndCapabilitiesOfCurrentIsolate()
+      native "Isolate_getPortAndCapabilitiesOfCurrentIsolate";
+
+  static Uri _getCurrentRootUri() {
+    try {
+      return Uri.parse(_getCurrentRootUriStr());
+    } catch (e) {
+      return null;
+    }
+  }
+
+  static String _getCurrentRootUriStr() native "Isolate_getCurrentRootUriStr";
+}
+
+@patch
+abstract class TransferableTypedData {
+  @patch
+  factory TransferableTypedData.fromList(List<TypedData> chunks) {
+    if (chunks == null) {
+      throw ArgumentError(chunks);
+    }
+    final int cid = ClassID.getID(chunks);
+    if (cid != ClassID.cidArray &&
+        cid != ClassID.cidGrowableObjectArray &&
+        cid != ClassID.cidImmutableArray) {
+      chunks = List.unmodifiable(chunks);
+    }
+    return _TransferableTypedDataImpl(chunks);
+  }
+}
+
+@pragma("vm:entry-point")
+class _TransferableTypedDataImpl implements TransferableTypedData {
+  factory _TransferableTypedDataImpl(List<TypedData> list)
+      native "TransferableTypedData_factory";
+
+  ByteBuffer materialize() {
+    return _materializeIntoUint8List().buffer;
+  }
+
+  Uint8List _materializeIntoUint8List()
+      native "TransferableTypedData_materialize";
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/lib_prefix.dart b/sdk_nnbd/lib/_internal/vm/lib/lib_prefix.dart
new file mode 100644
index 0000000..895e5cc
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/lib_prefix.dart
@@ -0,0 +1,19 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+// This type corresponds to the VM-internal class LibraryPrefix.
+@pragma("vm:entry-point")
+class _LibraryPrefix {
+  factory _LibraryPrefix._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  bool isLoaded() => true;
+
+  loadLibrary() => new Future.value(true);
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/map_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/map_patch.dart
new file mode 100644
index 0000000..9a014c6
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/map_patch.dart
@@ -0,0 +1,33 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+@patch
+class Map<K, V> {
+  // Factory constructing a Map from a parser generated Map literal.
+  // [elements] contains n key-value pairs.
+  // The keys are at position 2*n and are already type checked by the parser
+  // in checked mode.
+  // The values are at position 2*n+1 and are not yet type checked.
+  @pragma("vm:entry-point", "call")
+  factory Map._fromLiteral(List elements) {
+    var map = new LinkedHashMap<K, V>();
+    var len = elements.length;
+    for (int i = 1; i < len; i += 2) {
+      map[elements[i - 1]] = elements[i];
+    }
+    return map;
+  }
+
+  @patch
+  factory Map.unmodifiable(Map other) {
+    return new UnmodifiableMapView<K, V>(new Map<K, V>.from(other));
+  }
+
+  @patch
+  factory Map() => new LinkedHashMap<K, V>();
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/math_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/math_patch.dart
new file mode 100644
index 0000000..341d5eb
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/math_patch.dart
@@ -0,0 +1,315 @@
+// 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.
+
+// @dart = 2.5
+
+/// Note: the VM concatenates all patch files into a single patch file. This
+/// file is the first patch in "dart:math" which contains all the imports used
+/// by patches of that library. We plan to change this when we have a shared
+/// front end and simply use parts.
+
+import "dart:_internal" show patch;
+
+import "dart:typed_data" show Uint32List;
+
+/// There are no parts of this patch library.
+
+@patch
+@pragma("vm:prefer-inline")
+T min<T extends num>(T a, T b) {
+  // These partially redundant type checks improve code quality for dart2js.
+  // Most of the improvement is at call sites from the inferred non-null num
+  // return type.
+  if (a is! num) throw new ArgumentError(a);
+  if (b is! num) throw new ArgumentError(b);
+
+  if (a > b) return b;
+  if (a < b) return a;
+  if (b is double) {
+    // Special case for NaN and -0.0. If one argument is NaN return NaN.
+    // [min] must also distinguish between -0.0 and 0.0.
+    if (a is double) {
+      if (a == 0.0) {
+        // a is either 0.0 or -0.0. b is either 0.0, -0.0 or NaN.
+        // The following returns -0.0 if either a or b is -0.0, and it
+        // returns NaN if b is NaN.
+        num n = (a + b) * a * b;
+        return n;
+      }
+    }
+    // Check for NaN and b == -0.0.
+    if (a == 0 && b.isNegative || b.isNaN) return b;
+    return a;
+  }
+  return a;
+}
+
+@patch
+@pragma("vm:prefer-inline")
+T max<T extends num>(T a, T b) {
+  // These partially redundant type checks improve code quality for dart2js.
+  // Most of the improvement is at call sites from the inferred non-null num
+  // return type.
+  if (a is! num) throw new ArgumentError(a);
+  if (b is! num) throw new ArgumentError(b);
+
+  if (a > b) return a;
+  if (a < b) return b;
+  if (b is double) {
+    // Special case for NaN and -0.0. If one argument is NaN return NaN.
+    // [max] must also distinguish between -0.0 and 0.0.
+    if (a is double) {
+      if (a == 0.0) {
+        // a is either 0.0 or -0.0. b is either 0.0, -0.0, or NaN.
+        // The following returns 0.0 if either a or b is 0.0, and it
+        // returns NaN if b is NaN.
+        num n = a + b;
+        return n;
+      }
+    }
+    // Check for NaN.
+    if (b.isNaN) return b;
+    return a;
+  }
+  // max(-0.0, 0) must return 0.
+  if (b == 0 && a.isNegative) return b;
+  return a;
+}
+
+// If [x] is an [int] and [exponent] is a non-negative [int], the result is
+// an [int], otherwise the result is a [double].
+@patch
+@pragma("vm:prefer-inline")
+num pow(num x, num exponent) {
+  if ((x is int) && (exponent is int) && (exponent >= 0)) {
+    return _intPow(x, exponent);
+  }
+  return _doublePow(x.toDouble(), exponent.toDouble());
+}
+
+@pragma("vm:exact-result-type", "dart:core#_Double")
+double _doublePow(double base, double exponent) {
+  if (exponent == 0.0) {
+    return 1.0; // ECMA-262 15.8.2.13
+  }
+  // Speed up simple cases.
+  if (exponent == 1.0) return base;
+  if (exponent == 2.0) return base * base;
+  if (exponent == 3.0) return base * base * base;
+
+  if (base == 1.0) return 1.0;
+
+  if (base.isNaN || exponent.isNaN) {
+    return double.nan;
+  }
+  if ((base != -double.infinity) && (exponent == 0.5)) {
+    if (base == 0.0) {
+      return 0.0;
+    }
+    return sqrt(base);
+  }
+  return _pow(base.toDouble(), exponent.toDouble());
+}
+
+double _pow(double base, double exponent) native "Math_doublePow";
+
+int _intPow(int base, int exponent) {
+  // Exponentiation by squaring.
+  int result = 1;
+  while (exponent != 0) {
+    if ((exponent & 1) == 1) {
+      result *= base;
+    }
+    exponent >>= 1;
+    // Skip unnecessary operation (can overflow to Mint).
+    if (exponent != 0) {
+      base *= base;
+    }
+  }
+  return result;
+}
+
+@patch
+@pragma("vm:exact-result-type", "dart:core#_Double")
+@pragma("vm:never-inline")
+double atan2(num a, num b) => _atan2(a.toDouble(), b.toDouble());
+@patch
+@pragma("vm:exact-result-type", "dart:core#_Double")
+@pragma("vm:never-inline")
+double sin(num radians) => _sin(radians.toDouble());
+@patch
+@pragma("vm:exact-result-type", "dart:core#_Double")
+@pragma("vm:never-inline")
+double cos(num radians) => _cos(radians.toDouble());
+@patch
+@pragma("vm:exact-result-type", "dart:core#_Double")
+@pragma("vm:never-inline")
+double tan(num radians) => _tan(radians.toDouble());
+@patch
+@pragma("vm:exact-result-type", "dart:core#_Double")
+@pragma("vm:never-inline")
+double acos(num x) => _acos(x.toDouble());
+@patch
+@pragma("vm:exact-result-type", "dart:core#_Double")
+@pragma("vm:never-inline")
+double asin(num x) => _asin(x.toDouble());
+@patch
+@pragma("vm:exact-result-type", "dart:core#_Double")
+@pragma("vm:never-inline")
+double atan(num x) => _atan(x.toDouble());
+@patch
+@pragma("vm:exact-result-type", "dart:core#_Double")
+@pragma("vm:never-inline")
+double sqrt(num x) => _sqrt(x.toDouble());
+@patch
+@pragma("vm:prefer-inline")
+double exp(num x) => _exp(x.toDouble());
+@patch
+@pragma("vm:prefer-inline")
+double log(num x) => _log(x.toDouble());
+
+double _atan2(double a, double b) native "Math_atan2";
+double _sin(double x) native "Math_sin";
+double _cos(double x) native "Math_cos";
+double _tan(double x) native "Math_tan";
+double _acos(double x) native "Math_acos";
+double _asin(double x) native "Math_asin";
+double _atan(double x) native "Math_atan";
+double _sqrt(double x) native "Math_sqrt";
+double _exp(double x) native "Math_exp";
+double _log(double x) native "Math_log";
+
+// TODO(iposva): Handle patch methods within a patch class correctly.
+@patch
+class Random {
+  @patch
+  factory Random([int seed]) {
+    var state = _Random._setupSeed((seed == null) ? _Random._nextSeed() : seed);
+    // Crank a couple of times to distribute the seed bits a bit further.
+    return new _Random._withState(state)
+      .._nextState()
+      .._nextState()
+      .._nextState()
+      .._nextState();
+  }
+
+  @patch
+  factory Random.secure() {
+    return new _SecureRandom();
+  }
+}
+
+class _Random implements Random {
+  // Internal state of the random number generator.
+  @pragma("vm:entry-point")
+  final Uint32List _state;
+  static const _kSTATE_LO = 0;
+  static const _kSTATE_HI = 1; // Unused in Dart code.
+
+  _Random._withState(this._state);
+
+  // The algorithm used here is Multiply with Carry (MWC) with a Base b = 2^32.
+  // http://en.wikipedia.org/wiki/Multiply-with-carry
+  // The constant A is selected from "Numerical Recipes 3rd Edition" p.348 B1.
+
+  // Implements:
+  //   const _A = 0xffffda61;
+  //   var state =
+  //       ((_A * (_state[_kSTATE_LO])) + _state[_kSTATE_HI]) & ((1 << 64) - 1);
+  //   _state[_kSTATE_LO] = state & ((1 << 32) - 1);
+  //   _state[_kSTATE_HI] = state >> 32;
+  // This is a native to prevent 64-bit operations in Dart, which
+  // fail with --throw_on_javascript_int_overflow.
+  // TODO(regis): Implement in Dart and remove Random_nextState in math.cc.
+  void _nextState() native "Random_nextState";
+
+  int nextInt(int max) {
+    const limit = 0x3FFFFFFF;
+    if ((max <= 0) || ((max > limit) && (max > _POW2_32))) {
+      throw new RangeError.range(
+          max, 1, _POW2_32, "max", "Must be positive and <= 2^32");
+    }
+    if ((max & -max) == max) {
+      // Fast case for powers of two.
+      _nextState();
+      return _state[_kSTATE_LO] & (max - 1);
+    }
+
+    var rnd32;
+    var result;
+    do {
+      _nextState();
+      rnd32 = _state[_kSTATE_LO];
+      result = rnd32 % max;
+    } while ((rnd32 - result + max) > _POW2_32);
+    return result;
+  }
+
+  double nextDouble() {
+    return ((nextInt(1 << 26) * _POW2_27_D) + nextInt(1 << 27)) / _POW2_53_D;
+  }
+
+  bool nextBool() {
+    return nextInt(2) == 0;
+  }
+
+  // Constants used by the algorithm.
+  static const _POW2_32 = 1 << 32;
+  static const _POW2_53_D = 1.0 * (1 << 53);
+  static const _POW2_27_D = 1.0 * (1 << 27);
+
+  // Use a singleton Random object to get a new seed if no seed was passed.
+  static final _prng = new _Random._withState(_initialSeed());
+
+  // This is a native to prevent 64-bit operations in Dart, which
+  // fail with --throw_on_javascript_int_overflow.
+  // TODO(regis): Implement here in Dart and remove native in math.cc.
+  static Uint32List _setupSeed(int seed) native "Random_setupSeed";
+  // Get a seed from the VM's random number provider.
+  static Uint32List _initialSeed() native "Random_initialSeed";
+
+  static int _nextSeed() {
+    // Trigger the PRNG once to change the internal state.
+    _prng._nextState();
+    return _prng._state[_kSTATE_LO];
+  }
+}
+
+class _SecureRandom implements Random {
+  _SecureRandom() {
+    // Throw early in constructor if entropy source is not hooked up.
+    _getBytes(1);
+  }
+
+  // Return count bytes of entropy as a positive integer; count <= 8.
+  static int _getBytes(int count) native "SecureRandom_getBytes";
+
+  int nextInt(int max) {
+    RangeError.checkValueInInterval(
+        max, 1, _POW2_32, "max", "Must be positive and <= 2^32");
+    final byteCount = ((max - 1).bitLength + 7) >> 3;
+    if (byteCount == 0) {
+      return 0; // Not random if max == 1.
+    }
+    var rnd;
+    var result;
+    do {
+      rnd = _getBytes(byteCount);
+      result = rnd % max;
+    } while ((rnd - result + max) > (1 << (byteCount << 3)));
+    return result;
+  }
+
+  double nextDouble() {
+    return (_getBytes(7) >> 3) / _POW2_53_D;
+  }
+
+  bool nextBool() {
+    return _getBytes(1).isEven;
+  }
+
+  // Constants used by the algorithm.
+  static const _POW2_32 = 1 << 32;
+  static const _POW2_53_D = 1.0 * (1 << 53);
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/mirror_reference.dart b/sdk_nnbd/lib/_internal/vm/lib/mirror_reference.dart
new file mode 100644
index 0000000..a403f38
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/mirror_reference.dart
@@ -0,0 +1,16 @@
+// 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 "mirrors_patch.dart";
+
+@pragma("vm:entry-point")
+class _MirrorReference {
+  factory _MirrorReference._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  bool operator ==(other) native "MirrorReference_equals";
+}
diff --git a/runtime/lib/mirrors_impl.dart b/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart
similarity index 90%
rename from runtime/lib/mirrors_impl.dart
rename to sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart
index d6d07fd..f83fe33 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 // part of "mirrors_patch.dart";
 
 var _dirty = false; // Set to true by the VM when more libraries are loaded.
@@ -67,7 +69,7 @@
 
 bool _subtypeTest(Type a, Type b) native 'TypeMirror_subtypeTest';
 
-class _LocalMirrorSystem extends MirrorSystem {
+class _MirrorSystem extends MirrorSystem {
   final TypeMirror dynamicType = new _SpecialTypeMirror._('dynamic');
   final TypeMirror voidType = new _SpecialTypeMirror._('void');
 
@@ -114,13 +116,11 @@
   }
 }
 
-abstract class _LocalMirror implements Mirror {}
-
-class _LocalIsolateMirror extends _LocalMirror implements IsolateMirror {
+class _IsolateMirror extends Mirror implements IsolateMirror {
   final String debugName;
   final LibraryMirror rootLibrary;
 
-  _LocalIsolateMirror._(this.debugName, this.rootLibrary);
+  _IsolateMirror._(this.debugName, this.rootLibrary);
 
   bool get isCurrent => true;
 
@@ -201,14 +201,14 @@
   List<InstanceMirror> get metadata => const <InstanceMirror>[];
 }
 
-abstract class _LocalObjectMirror extends _LocalMirror implements ObjectMirror {
+abstract class _ObjectMirror extends Mirror implements ObjectMirror {
   _invoke(reflectee, functionName, arguments, argumentNames);
   _invokeGetter(reflectee, getterName);
   _invokeSetter(reflectee, setterName, value);
 
   final _reflectee; // May be a MirrorReference or an ordinary object.
 
-  _LocalObjectMirror._(this._reflectee);
+  _ObjectMirror._(this._reflectee);
 
   InstanceMirror invoke(Symbol memberName, List positionalArguments,
       [Map<Symbol, dynamic> namedArguments]) {
@@ -260,9 +260,8 @@
   }
 }
 
-class _LocalInstanceMirror extends _LocalObjectMirror
-    implements InstanceMirror {
-  _LocalInstanceMirror._(reflectee) : super._(reflectee);
+class _InstanceMirror extends _ObjectMirror implements InstanceMirror {
+  _InstanceMirror._(reflectee) : super._(reflectee);
 
   ClassMirror _type;
   ClassMirror get type {
@@ -282,8 +281,7 @@
   String toString() => 'InstanceMirror on ${Error.safeToString(_reflectee)}';
 
   bool operator ==(other) {
-    return other is _LocalInstanceMirror &&
-        identical(_reflectee, other._reflectee);
+    return other is _InstanceMirror && identical(_reflectee, other._reflectee);
   }
 
   int get hashCode {
@@ -334,9 +332,8 @@
   static _computeType(reflectee) native 'InstanceMirror_computeType';
 }
 
-class _LocalClosureMirror extends _LocalInstanceMirror
-    implements ClosureMirror {
-  _LocalClosureMirror._(reflectee) : super._(reflectee);
+class _ClosureMirror extends _InstanceMirror implements ClosureMirror {
+  _ClosureMirror._(reflectee) : super._(reflectee);
 
   MethodMirror _function;
   MethodMirror get function {
@@ -356,12 +353,11 @@
   static _computeFunction(reflectee) native 'ClosureMirror_function';
 }
 
-abstract class _LocalTypeMirror {
+abstract class _TypeMirror {
   Type get _reflectedType;
 }
 
-class _LocalClassMirror extends _LocalObjectMirror
-    implements ClassMirror, _LocalTypeMirror {
+class _ClassMirror extends _ObjectMirror implements ClassMirror, _TypeMirror {
   final Type _reflectedType;
   Symbol _simpleName;
   DeclarationMirror _owner;
@@ -377,7 +373,7 @@
   final bool isEnum;
   Type _instantiator;
 
-  _LocalClassMirror._(
+  _ClassMirror._(
       reflectee,
       reflectedType,
       String simpleName,
@@ -419,7 +415,7 @@
 
   DeclarationMirror get owner {
     if (_owner == null) {
-      var uri = _LocalClassMirror._libraryUri(_reflectee);
+      var uri = _ClassMirror._libraryUri(_reflectee);
       _owner = currentMirrorSystem().libraries[Uri.parse(uri)];
     }
     return _owner;
@@ -433,8 +429,8 @@
     return _location(_reflectee);
   }
 
-  _LocalClassMirror _trueSuperclassField;
-  _LocalClassMirror get _trueSuperclass {
+  _ClassMirror _trueSuperclassField;
+  _ClassMirror get _trueSuperclass {
     if (_trueSuperclassField == null) {
       Type supertype = isOriginalDeclaration
           ? _supertype(_reflectedType)
@@ -487,8 +483,7 @@
   var _mixin;
   ClassMirror get mixin {
     if (_mixin == null) {
-      Type mixinType =
-          _nativeMixinInstantiated(_reflectedType, _instantiator);
+      Type mixinType = _nativeMixinInstantiated(_reflectedType, _instantiator);
       if (mixinType == null) {
         // The reflectee is not a mixin application.
         _mixin = this;
@@ -599,7 +594,7 @@
       ClassMirror owner = originalDeclaration;
       var mirror;
       for (var i = 0; i < params.length; i += 2) {
-        mirror = new _LocalTypeVariableMirror._(params[i + 1], params[i], owner);
+        mirror = new _TypeVariableMirror._(params[i + 1], params[i], owner);
         _typeVariables.add(mirror);
       }
       _typeVariables =
@@ -676,14 +671,13 @@
   bool isSubtypeOf(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
     if (other == currentMirrorSystem().voidType) return false;
-    return _subtypeTest(
-        _reflectedType, (other as _LocalTypeMirror)._reflectedType);
+    return _subtypeTest(_reflectedType, (other as _TypeMirror)._reflectedType);
   }
 
   bool isAssignableTo(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
     if (other == currentMirrorSystem().voidType) return false;
-    final otherReflectedType = (other as _LocalTypeMirror)._reflectedType;
+    final otherReflectedType = (other as _TypeMirror)._reflectedType;
     return _subtypeTest(_reflectedType, otherReflectedType) ||
         _subtypeTest(otherReflectedType, _reflectedType);
   }
@@ -741,12 +735,11 @@
       native "ClassMirror_type_arguments";
 }
 
-class _LocalFunctionTypeMirror extends _LocalClassMirror
-    implements FunctionTypeMirror {
+class _FunctionTypeMirror extends _ClassMirror implements FunctionTypeMirror {
   final _functionReflectee;
-  _LocalFunctionTypeMirror._(reflectee, this._functionReflectee, reflectedType)
-      : super._(reflectee, reflectedType, null, null, false, false, false, false,
-            false);
+  _FunctionTypeMirror._(reflectee, this._functionReflectee, reflectedType)
+      : super._(reflectee, reflectedType, null, null, false, false, false,
+            false, false);
 
   bool get _isAnonymousMixinApplication => false;
 
@@ -805,12 +798,11 @@
       native "FunctionTypeMirror_parameters";
 }
 
-abstract class _LocalDeclarationMirror extends _LocalMirror
-    implements DeclarationMirror {
+abstract class _DeclarationMirror extends Mirror implements DeclarationMirror {
   final _reflectee;
   Symbol _simpleName;
 
-  _LocalDeclarationMirror._(this._reflectee, this._simpleName);
+  _DeclarationMirror._(this._reflectee, this._simpleName);
 
   Symbol get simpleName => _simpleName;
 
@@ -843,9 +835,9 @@
   int get hashCode => simpleName.hashCode;
 }
 
-class _LocalTypeVariableMirror extends _LocalDeclarationMirror
-    implements TypeVariableMirror, _LocalTypeMirror {
-  _LocalTypeVariableMirror._(reflectee, String simpleName, this._owner)
+class _TypeVariableMirror extends _DeclarationMirror
+    implements TypeVariableMirror, _TypeMirror {
+  _TypeVariableMirror._(reflectee, String simpleName, this._owner)
       : super._(reflectee, _s(simpleName));
 
   DeclarationMirror _owner;
@@ -894,14 +886,13 @@
   bool isSubtypeOf(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
     if (other == currentMirrorSystem().voidType) return false;
-    return _subtypeTest(
-        _reflectedType, (other as _LocalTypeMirror)._reflectedType);
+    return _subtypeTest(_reflectedType, (other as _TypeMirror)._reflectedType);
   }
 
   bool isAssignableTo(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
     if (other == currentMirrorSystem().voidType) return false;
-    final otherReflectedType = (other as _LocalTypeMirror)._reflectedType;
+    final otherReflectedType = (other as _TypeMirror)._reflectedType;
     return _subtypeTest(_reflectedType, otherReflectedType) ||
         _subtypeTest(otherReflectedType, _reflectedType);
   }
@@ -913,13 +904,13 @@
       native "TypeVariableMirror_upper_bound";
 }
 
-class _LocalTypedefMirror extends _LocalDeclarationMirror
-    implements TypedefMirror, _LocalTypeMirror {
+class _TypedefMirror extends _DeclarationMirror
+    implements TypedefMirror, _TypeMirror {
   final Type _reflectedType;
   final bool _isGeneric;
   final bool _isGenericDeclaration;
 
-  _LocalTypedefMirror(reflectee, this._reflectedType, String simpleName,
+  _TypedefMirror(reflectee, this._reflectedType, String simpleName,
       this._isGeneric, this._isGenericDeclaration, this._owner)
       : super._(reflectee, _s(simpleName));
 
@@ -928,13 +919,13 @@
   DeclarationMirror _owner;
   DeclarationMirror get owner {
     if (_owner == null) {
-      var uri = _LocalClassMirror._libraryUri(_reflectee);
+      var uri = _ClassMirror._libraryUri(_reflectee);
       _owner = currentMirrorSystem().libraries[Uri.parse(uri)];
     }
     return _owner;
   }
 
-  _LocalFunctionTypeMirror _referent;
+  _FunctionTypeMirror _referent;
   FunctionTypeMirror get referent {
     if (_referent == null) {
       _referent = _nativeReferent(_reflectedType);
@@ -966,11 +957,11 @@
   List<TypeVariableMirror> get typeVariables {
     if (_typeVariables == null) {
       _typeVariables = new List<TypeVariableMirror>();
-      List params = _LocalClassMirror._ClassMirror_type_variables(_reflectee);
+      List params = _ClassMirror._ClassMirror_type_variables(_reflectee);
       TypedefMirror owner = originalDeclaration;
       var mirror;
       for (var i = 0; i < params.length; i += 2) {
-        mirror = new _LocalTypeVariableMirror._(params[i + 1], params[i], owner);
+        mirror = new _TypeVariableMirror._(params[i + 1], params[i], owner);
         _typeVariables.add(mirror);
       }
     }
@@ -983,9 +974,9 @@
       if (_isGenericDeclaration) {
         _typeArguments = const <TypeMirror>[];
       } else {
-        _typeArguments = new UnmodifiableListView<TypeMirror>(_LocalClassMirror
-            ._computeTypeArguments(_reflectedType)
-            .cast<TypeMirror>());
+        _typeArguments = new UnmodifiableListView<TypeMirror>(
+            _ClassMirror._computeTypeArguments(_reflectedType)
+                .cast<TypeMirror>());
       }
     }
     return _typeArguments;
@@ -996,14 +987,13 @@
   bool isSubtypeOf(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
     if (other == currentMirrorSystem().voidType) return false;
-    return _subtypeTest(
-        _reflectedType, (other as _LocalTypeMirror)._reflectedType);
+    return _subtypeTest(_reflectedType, (other as _TypeMirror)._reflectedType);
   }
 
   bool isAssignableTo(TypeMirror other) {
     if (other == currentMirrorSystem().dynamicType) return true;
     if (other == currentMirrorSystem().voidType) return false;
-    final otherReflectedType = (other as _LocalTypeMirror)._reflectedType;
+    final otherReflectedType = (other as _TypeMirror)._reflectedType;
     return _subtypeTest(_reflectedType, otherReflectedType) ||
         _subtypeTest(otherReflectedType, _reflectedType);
   }
@@ -1020,11 +1010,11 @@
   return MirrorSystem.getSymbol('${unwrapped}=', library);
 }
 
-class _LocalLibraryMirror extends _LocalObjectMirror implements LibraryMirror {
+class _LibraryMirror extends _ObjectMirror implements LibraryMirror {
   final Symbol simpleName;
   final Uri uri;
 
-  _LocalLibraryMirror._(reflectee, String simpleName, String url)
+  _LibraryMirror._(reflectee, String simpleName, String url)
       : this.simpleName = _s(simpleName),
         this.uri = Uri.parse(url),
         super._(reflectee);
@@ -1097,7 +1087,7 @@
   List<dynamic> _computeMembers(reflectee) native "LibraryMirror_members";
 }
 
-class _LocalLibraryDependencyMirror extends _LocalMirror
+class _LibraryDependencyMirror extends Mirror
     implements LibraryDependencyMirror {
   final LibraryMirror sourceLibrary;
   var _targetMirrorOrPrefix;
@@ -1107,7 +1097,7 @@
   final bool isDeferred;
   final List<InstanceMirror> metadata;
 
-  _LocalLibraryDependencyMirror._(
+  _LibraryDependencyMirror._(
       this.sourceLibrary,
       this._targetMirrorOrPrefix,
       List<dynamic> mutableCombinators,
@@ -1124,7 +1114,7 @@
   bool get isExport => !isImport;
 
   LibraryMirror get targetLibrary {
-    if (_targetMirrorOrPrefix is _LocalLibraryMirror) {
+    if (_targetMirrorOrPrefix is _LibraryMirror) {
       return _targetMirrorOrPrefix;
     }
     var mirrorOrNull = _tryUpgradePrefix(_targetMirrorOrPrefix);
@@ -1135,7 +1125,7 @@
   }
 
   Future<LibraryMirror> loadLibrary() {
-    if (_targetMirrorOrPrefix is _LocalLibraryMirror) {
+    if (_targetMirrorOrPrefix is _LibraryMirror) {
       return new Future.value(_targetMirrorOrPrefix);
     }
     var savedPrefix = _targetMirrorOrPrefix;
@@ -1150,25 +1140,24 @@
   SourceLocation get location => null;
 }
 
-class _LocalCombinatorMirror extends _LocalMirror implements CombinatorMirror {
+class _CombinatorMirror extends Mirror implements CombinatorMirror {
   final List<Symbol> identifiers;
   final bool isShow;
 
-  _LocalCombinatorMirror._(identifierString, this.isShow)
+  _CombinatorMirror._(identifierString, this.isShow)
       : this.identifiers =
             new UnmodifiableListView<Symbol>(<Symbol>[_s(identifierString)]);
 
   bool get isHide => !isShow;
 }
 
-class _LocalMethodMirror extends _LocalDeclarationMirror
-    implements MethodMirror {
+class _MethodMirror extends _DeclarationMirror implements MethodMirror {
   final Type _instantiator;
   final bool isStatic;
   final int _kindFlags;
 
-  _LocalMethodMirror._(reflectee, String simpleName, this._owner,
-      this._instantiator, this.isStatic, this._kindFlags)
+  _MethodMirror._(reflectee, String simpleName, this._owner, this._instantiator,
+      this.isStatic, this._kindFlags)
       : super._(reflectee, _s(simpleName));
 
   static const kAbstract = 0;
@@ -1289,14 +1278,13 @@
   static String _MethodMirror_source(reflectee) native "MethodMirror_source";
 }
 
-class _LocalVariableMirror extends _LocalDeclarationMirror
-    implements VariableMirror {
+class _VariableMirror extends _DeclarationMirror implements VariableMirror {
   final DeclarationMirror owner;
   final bool isStatic;
   final bool isFinal;
   final bool isConst;
 
-  _LocalVariableMirror._(reflectee, String simpleName, this.owner, this._type,
+  _VariableMirror._(reflectee, String simpleName, this.owner, this._type,
       this.isStatic, this.isFinal, this.isConst)
       : super._(reflectee, _s(simpleName));
 
@@ -1304,11 +1292,11 @@
 
   Type get _instantiator {
     final o = owner; // Note: need local variable for promotion to happen.
-    if (o is _LocalClassMirror) {
+    if (o is _ClassMirror) {
       return o._instantiator;
-    } else if (o is _LocalMethodMirror) {
+    } else if (o is _MethodMirror) {
       return o._instantiator;
-    } else if (o is _LocalLibraryMirror) {
+    } else if (o is _LibraryMirror) {
       return o._instantiator;
     } else {
       throw new UnsupportedError("unexpected owner ${owner}");
@@ -1330,14 +1318,13 @@
       native "VariableMirror_type";
 }
 
-class _LocalParameterMirror extends _LocalVariableMirror
-    implements ParameterMirror {
+class _ParameterMirror extends _VariableMirror implements ParameterMirror {
   final int _position;
   final bool isOptional;
   final bool isNamed;
   final List _unmirroredMetadata;
 
-  _LocalParameterMirror._(
+  _ParameterMirror._(
       reflectee,
       String simpleName,
       DeclarationMirror owner,
@@ -1396,7 +1383,7 @@
       native "ParameterMirror_type";
 }
 
-class _SpecialTypeMirror extends _LocalMirror
+class _SpecialTypeMirror extends Mirror
     implements TypeMirror, DeclarationMirror {
   final Symbol simpleName;
 
@@ -1445,7 +1432,7 @@
 }
 
 class _Mirrors {
-  static MirrorSystem _currentMirrorSystem = new _LocalMirrorSystem();
+  static MirrorSystem _currentMirrorSystem = new _MirrorSystem();
   static MirrorSystem currentMirrorSystem() {
     return _currentMirrorSystem;
   }
@@ -1453,8 +1440,8 @@
   // Creates a new local mirror for some Object.
   static InstanceMirror reflect(Object reflectee) {
     return reflectee is Function
-        ? new _LocalClosureMirror._(reflectee)
-        : new _LocalInstanceMirror._(reflectee);
+        ? new _ClosureMirror._(reflectee)
+        : new _InstanceMirror._(reflectee);
   }
 
   static ClassMirror _makeLocalClassMirror(Type key)
@@ -1464,8 +1451,7 @@
   static Type _instantiateGenericType(Type key, typeArguments)
       native "Mirrors_instantiateGenericType";
 
-  static Expando<_LocalClassMirror> _declarationCache =
-      new Expando("ClassMirror");
+  static Expando<_ClassMirror> _declarationCache = new Expando("ClassMirror");
   static Expando<TypeMirror> _instantiationCache = new Expando("TypeMirror");
 
   static ClassMirror reflectClass(Type key) {
@@ -1488,7 +1474,7 @@
     if (typeMirror == null) {
       typeMirror = _makeLocalTypeMirror(key);
       _instantiationCache[key] = typeMirror;
-      if (typeMirror is _LocalClassMirror && !typeMirror._isGeneric) {
+      if (typeMirror is _ClassMirror && !typeMirror._isGeneric) {
         _declarationCache[key] = typeMirror;
       }
     }
diff --git a/runtime/lib/mirrors_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/mirrors_patch.dart
similarity index 98%
rename from runtime/lib/mirrors_patch.dart
rename to sdk_nnbd/lib/_internal/vm/lib/mirrors_patch.dart
index 623fd65..4c8a2f8 100644
--- a/runtime/lib/mirrors_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/mirrors_patch.dart
@@ -2,6 +2,8 @@
 // for details. All 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:_internal" which contains all the imports
 /// used by patches of that library. We plan to change this when we have a
diff --git a/sdk_nnbd/lib/_internal/vm/lib/null_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/null_patch.dart
new file mode 100644
index 0000000..ba721ad
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/null_patch.dart
@@ -0,0 +1,18 @@
+// 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 "core_patch.dart";
+
+@patch
+@pragma("vm:entry-point")
+class Null {
+  static const _HASH_CODE = 2011; // The year Dart was announced and a prime.
+
+  @patch
+  int get hashCode => _HASH_CODE;
+
+  int get _identityHashCode => _HASH_CODE;
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/object_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/object_patch.dart
new file mode 100644
index 0000000..9930fe7
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/object_patch.dart
@@ -0,0 +1,77 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+@pragma("vm:exact-result-type", "dart:core#_Smi")
+int _getHash(obj) native "Object_getHash";
+void _setHash(obj, hash) native "Object_setHash";
+
+@patch
+@pragma("vm:entry-point")
+class Object {
+  // The VM has its own implementation of equals.
+  @patch
+  @pragma("vm:exact-result-type", bool)
+  @pragma("vm:prefer-inline")
+  bool operator ==(other) native "Object_equals";
+
+  // Helpers used to implement hashCode. If a hashCode is used, we remember it
+  // in a weak table in the VM (32 bit) or in the header of the object (64
+  // bit). A new hashCode value is calculated using a random number generator.
+  static final _hashCodeRnd = new Random();
+
+  static int _objectHashCode(obj) {
+    var result = _getHash(obj);
+    if (result == 0) {
+      // We want the hash to be a Smi value greater than 0.
+      result = _hashCodeRnd.nextInt(0x40000000);
+      do {
+        result = _hashCodeRnd.nextInt(0x40000000);
+      } while (result == 0);
+      _setHash(obj, result);
+    }
+    return result;
+  }
+
+  @patch
+  int get hashCode => _objectHashCode(this);
+  int get _identityHashCode => _objectHashCode(this);
+
+  @patch
+  String toString() native "Object_toString";
+  // A statically dispatched version of Object.toString.
+  static String _toString(obj) native "Object_toString";
+
+  @patch
+  @pragma("vm:entry-point", "call")
+  dynamic noSuchMethod(Invocation invocation) {
+    // TODO(regis): Remove temp constructor identifier 'withInvocation'.
+    throw new NoSuchMethodError.withInvocation(this, invocation);
+  }
+
+  @patch
+  @pragma("vm:exact-result-type", "dart:core#_Type")
+  Type get runtimeType native "Object_runtimeType";
+
+  @pragma("vm:entry-point", "call")
+  @pragma("vm:exact-result-type", bool)
+  static bool _haveSameRuntimeType(a, b) native "Object_haveSameRuntimeType";
+
+  // Call this function instead of inlining instanceof, thus collecting
+  // type feedback and reducing code size of unoptimized code.
+  @pragma("vm:entry-point", "call")
+  bool _instanceOf(instantiatorTypeArguments, functionTypeArguments, type)
+      native "Object_instanceOf";
+
+  // Group of functions for implementing fast simple instance of.
+  @pragma("vm:entry-point", "call")
+  bool _simpleInstanceOf(type) native "Object_simpleInstanceOf";
+  @pragma("vm:entry-point", "call")
+  bool _simpleInstanceOfTrue(type) => true;
+  @pragma("vm:entry-point", "call")
+  bool _simpleInstanceOfFalse(type) => false;
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/print_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/print_patch.dart
new file mode 100644
index 0000000..a8ecb6b
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/print_patch.dart
@@ -0,0 +1,25 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "internal_patch.dart";
+
+// A print-closure gets a String that should be printed. In general the
+// string is a line, but it may contain "\n" characters.
+typedef void _PrintClosure(String line);
+
+@patch
+void printToConsole(String line) {
+  _printClosure(line);
+}
+
+void _unsupportedPrint(String line) {
+  throw new UnsupportedError("'print' is not supported");
+}
+
+// _printClosure can be overwritten by the embedder to supply a different
+// print implementation.
+@pragma("vm:entry-point")
+_PrintClosure _printClosure = _unsupportedPrint;
diff --git a/sdk_nnbd/lib/_internal/vm/lib/profiler.dart b/sdk_nnbd/lib/_internal/vm/lib/profiler.dart
new file mode 100644
index 0000000..2ecd7e0
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/profiler.dart
@@ -0,0 +1,30 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "developer.dart";
+
+@patch
+class UserTag {
+  @patch
+  factory UserTag(String label) {
+    return new _UserTag(label);
+  }
+  @patch
+  static UserTag get defaultTag => _getDefaultTag();
+}
+
+@pragma("vm:entry-point")
+class _UserTag implements UserTag {
+  factory _UserTag(String label) native "UserTag_new";
+  String get label native "UserTag_label";
+  UserTag makeCurrent() native "UserTag_makeCurrent";
+}
+
+@patch
+UserTag getCurrentTag() => _getCurrentTag();
+UserTag _getCurrentTag() native "Profiler_getCurrentTag";
+
+UserTag _getDefaultTag() native "UserTag_defaultTag";
diff --git a/sdk_nnbd/lib/_internal/vm/lib/regexp_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/regexp_patch.dart
new file mode 100644
index 0000000..e97b977
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/regexp_patch.dart
@@ -0,0 +1,405 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+@patch
+class RegExp {
+  @patch
+  factory RegExp(String source,
+      {bool multiLine: false,
+      bool caseSensitive: true,
+      bool unicode: false,
+      bool dotAll: false}) {
+    _RegExpHashKey key =
+        new _RegExpHashKey(source, multiLine, caseSensitive, unicode, dotAll);
+    _RegExpHashValue value = _cache[key];
+
+    if (value == null) {
+      if (_cache.length > _MAX_CACHE_SIZE) {
+        _RegExpHashKey lastKey = _recentlyUsed.last;
+        _recentlyUsed.remove(lastKey);
+        _cache.remove(lastKey);
+      }
+
+      value = new _RegExpHashValue(
+          new _RegExp(source,
+              multiLine: multiLine,
+              caseSensitive: caseSensitive,
+              unicode: unicode,
+              dotAll: dotAll),
+          key);
+      _cache[key] = value;
+    } else {
+      value.key.unlink();
+    }
+
+    assert(value != null);
+
+    _recentlyUsed.addFirst(value.key);
+    assert(_recentlyUsed.length == _cache.length);
+
+    // TODO(zerny): We might not want to canonicalize regexp objects.
+    return value.regexp;
+  }
+
+  /**
+   * Finds the index of the first RegExp-significant char in [text].
+   *
+   * Starts looking from [start]. Returns `text.length` if no character
+   * is found that has special meaning in RegExp syntax.
+   */
+  static int _findEscapeChar(String text, int start) {
+    // Table where each character in the range U+0000 to U+007f is represented
+    // by whether it needs to be escaped in a regexp.
+    // The \x00 characters means escacped, and \x01 means non-escaped.
+    const escapes =
+        "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
+        "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
+        //                 $               (   )   *   +           .
+        "\x01\x01\x01\x01\x00\x01\x01\x01\x00\x00\x00\x00\x01\x01\x00\x01"
+        //                                                             ?
+        "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00"
+        "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
+        //                                             [   \   ]   ^
+        "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x01"
+        "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
+        //                                             {   |   }
+        "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x01\x01";
+    for (int i = start; i < text.length; i++) {
+      int char = text.codeUnitAt(i);
+      if (char <= 0x7f && escapes.codeUnitAt(char) == 0) return i;
+    }
+    return text.length;
+  }
+
+  @patch
+  static String escape(String text) {
+    int escapeCharIndex = _findEscapeChar(text, 0);
+    // If the text contains no characters needing escape, return it directly.
+    if (escapeCharIndex == text.length) return text;
+
+    var buffer = new StringBuffer();
+    int previousSliceEndIndex = 0;
+    do {
+      // Copy characters from previous escape to current escape into result.
+      // This includes the previously escaped character.
+      buffer.write(text.substring(previousSliceEndIndex, escapeCharIndex));
+      // Prepare the current character to be escaped by prefixing it with a '\'.
+      buffer.write(r"\");
+      previousSliceEndIndex = escapeCharIndex;
+      escapeCharIndex = _findEscapeChar(text, escapeCharIndex + 1);
+    } while (escapeCharIndex < text.length);
+    // Copy tail of string into result.
+    buffer.write(text.substring(previousSliceEndIndex, escapeCharIndex));
+    return buffer.toString();
+  }
+
+  // Regular expression objects are stored in a cache of up to _MAX_CACHE_SIZE
+  // elements using an LRU eviction strategy.
+  // TODO(zerny): Do not impose a fixed limit on the number of cached objects.
+  // Other possibilities could be limiting by the size of the regexp objects,
+  // or imposing a lower time bound for the most recent use under which a regexp
+  // may not be removed from the cache.
+  // TODO(zerny): Use self-sizing cache similar to _AccessorCache in
+  // mirrors_impl.dart.
+  static const int _MAX_CACHE_SIZE = 256;
+  static final Map<_RegExpHashKey, _RegExpHashValue> _cache =
+      new HashMap<_RegExpHashKey, _RegExpHashValue>();
+  static final LinkedList<_RegExpHashKey> _recentlyUsed =
+      new LinkedList<_RegExpHashKey>();
+
+  int get _groupCount;
+  Iterable<String> get _groupNames;
+  int _groupNameIndex(String name);
+}
+
+// Represents both a key in the regular expression cache as well as its
+// corresponding entry in the LRU list.
+class _RegExpHashKey extends LinkedListEntry<_RegExpHashKey> {
+  final String pattern;
+  final bool multiLine;
+  final bool caseSensitive;
+  final bool unicode;
+  final bool dotAll;
+
+  _RegExpHashKey(this.pattern, this.multiLine, this.caseSensitive, this.unicode,
+      this.dotAll);
+
+  int get hashCode => pattern.hashCode;
+  bool operator ==(that) {
+    return (that is _RegExpHashKey) &&
+        (this.pattern == that.pattern) &&
+        (this.multiLine == that.multiLine) &&
+        (this.caseSensitive == that.caseSensitive) &&
+        (this.unicode == that.unicode) &&
+        (this.dotAll == that.dotAll);
+  }
+}
+
+// Represents a value in the regular expression cache. Contains a pointer
+// back to the key in order to access the corresponding LRU entry.
+class _RegExpHashValue {
+  final _RegExp regexp;
+  final _RegExpHashKey key;
+
+  _RegExpHashValue(this.regexp, this.key);
+}
+
+class _RegExpMatch implements RegExpMatch {
+  _RegExpMatch._(this._regexp, this.input, this._match);
+
+  int get start => _start(0);
+  int get end => _end(0);
+
+  int _start(int groupIdx) {
+    return _match[(groupIdx * _MATCH_PAIR)];
+  }
+
+  int _end(int groupIdx) {
+    return _match[(groupIdx * _MATCH_PAIR) + 1];
+  }
+
+  String group(int groupIdx) {
+    if (groupIdx < 0 || groupIdx > _regexp._groupCount) {
+      throw new RangeError.value(groupIdx);
+    }
+    int startIndex = _start(groupIdx);
+    int endIndex = _end(groupIdx);
+    if (startIndex == -1) {
+      assert(endIndex == -1);
+      return null;
+    }
+    return input._substringUnchecked(startIndex, endIndex);
+  }
+
+  String operator [](int groupIdx) {
+    return this.group(groupIdx);
+  }
+
+  List<String> groups(List<int> groupsSpec) {
+    var groupsList = new List<String>(groupsSpec.length);
+    for (int i = 0; i < groupsSpec.length; i++) {
+      groupsList[i] = group(groupsSpec[i]);
+    }
+    return groupsList;
+  }
+
+  int get groupCount => _regexp._groupCount;
+
+  Pattern get pattern => _regexp;
+
+  String namedGroup(String name) {
+    var idx = _regexp._groupNameIndex(name);
+    if (idx < 0) {
+      throw ArgumentError("Not a capture group name: ${name}");
+    }
+    return group(idx);
+  }
+
+  Iterable<String> get groupNames {
+    return _regexp._groupNames;
+  }
+
+  final RegExp _regexp;
+  final String input;
+  final List<int> _match;
+  static const int _MATCH_PAIR = 2;
+}
+
+@pragma("vm:entry-point")
+class _RegExp implements RegExp {
+  factory _RegExp(String pattern,
+      {bool multiLine: false,
+      bool caseSensitive: true,
+      bool unicode: false,
+      bool dotAll: false}) native "RegExp_factory";
+
+  RegExpMatch firstMatch(String str) {
+    if (str is! String) throw new ArgumentError(str);
+    List match = _ExecuteMatch(str, 0);
+    if (match == null) {
+      return null;
+    }
+    return new _RegExpMatch._(this, str, match);
+  }
+
+  Iterable<RegExpMatch> allMatches(String string, [int start = 0]) {
+    if (string is! String) throw new ArgumentError(string);
+    if (start is! int) throw new ArgumentError(start);
+    if (0 > start || start > string.length) {
+      throw new RangeError.range(start, 0, string.length);
+    }
+    return new _AllMatchesIterable(this, string, start);
+  }
+
+  RegExpMatch matchAsPrefix(String string, [int start = 0]) {
+    if (string is! String) throw new ArgumentError(string);
+    if (start is! int) throw new ArgumentError(start);
+    if (start < 0 || start > string.length) {
+      throw new RangeError.range(start, 0, string.length);
+    }
+    List<int> list = _ExecuteMatchSticky(string, start);
+    if (list == null) return null;
+    return new _RegExpMatch._(this, string, list);
+  }
+
+  bool hasMatch(String str) {
+    if (str is! String) throw new ArgumentError(str);
+    List match = _ExecuteMatch(str, 0);
+    return (match == null) ? false : true;
+  }
+
+  String stringMatch(String str) {
+    if (str is! String) throw new ArgumentError(str);
+    List match = _ExecuteMatch(str, 0);
+    if (match == null) {
+      return null;
+    }
+    return str._substringUnchecked(match[0], match[1]);
+  }
+
+  String get pattern native "RegExp_getPattern";
+
+  bool get isMultiLine native "RegExp_getIsMultiLine";
+
+  bool get isCaseSensitive native "RegExp_getIsCaseSensitive";
+
+  bool get isUnicode native "RegExp_getIsUnicode";
+
+  bool get isDotAll native "RegExp_getIsDotAll";
+
+  int get _groupCount native "RegExp_getGroupCount";
+
+  // Returns a List [String, int, String, int, ...] where each
+  // String is the name of a capture group and the following
+  // int is that capture group's index.
+  List get _groupNameList native "RegExp_getGroupNameMap";
+
+  Iterable<String> get _groupNames sync* {
+    final nameList = _groupNameList;
+    for (var i = 0; i < nameList.length; i += 2) {
+      yield nameList[i] as String;
+    }
+  }
+
+  int _groupNameIndex(String name) {
+    var nameList = _groupNameList;
+    for (var i = 0; i < nameList.length; i += 2) {
+      if (name == nameList[i]) {
+        return nameList[i + 1];
+      }
+    }
+    return -1;
+  }
+
+  // Byte map of one byte characters with a 0xff if the character is a word
+  // character (digit, letter or underscore) and 0x00 otherwise.
+  // Used by generated RegExp code.
+  static const List<int> _wordCharacterMap = const <int>[
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // '0' - '7'
+    0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // '8' - '9'
+
+    0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'A' - 'G'
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'H' - 'O'
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'P' - 'W'
+    0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, // 'X' - 'Z', '_'
+
+    0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'a' - 'g'
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'h' - 'o'
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // 'p' - 'w'
+    0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, // 'x' - 'z'
+    // Latin-1 range
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  ];
+
+  List _ExecuteMatch(String str, int start_index) native "RegExp_ExecuteMatch";
+
+  List _ExecuteMatchSticky(String str, int start_index)
+      native "RegExp_ExecuteMatchSticky";
+}
+
+class _AllMatchesIterable extends IterableBase<RegExpMatch> {
+  final _RegExp _re;
+  final String _str;
+  final int _start;
+
+  _AllMatchesIterable(this._re, this._str, this._start);
+
+  Iterator<RegExpMatch> get iterator =>
+      new _AllMatchesIterator(_re, _str, _start);
+}
+
+class _AllMatchesIterator implements Iterator<RegExpMatch> {
+  final String _str;
+  int _nextIndex;
+  _RegExp _re;
+  RegExpMatch _current;
+
+  _AllMatchesIterator(this._re, this._str, this._nextIndex);
+
+  RegExpMatch get current => _current;
+
+  static bool _isLeadSurrogate(int c) {
+    return c >= 0xd800 && c <= 0xdbff;
+  }
+
+  static bool _isTrailSurrogate(int c) {
+    return c >= 0xdc00 && c <= 0xdfff;
+  }
+
+  bool moveNext() {
+    if (_re == null) return false; // Cleared after a failed match.
+    if (_nextIndex <= _str.length) {
+      var match = _re._ExecuteMatch(_str, _nextIndex);
+      if (match != null) {
+        _current = new _RegExpMatch._(_re, _str, match);
+        _nextIndex = _current.end;
+        if (_nextIndex == _current.start) {
+          // Zero-width match. Advance by one more, unless the regexp
+          // is in unicode mode and it would put us within a surrogate
+          // pair. In that case, advance past the code point as a whole.
+          if (_re.isUnicode &&
+              _nextIndex + 1 < _str.length &&
+              _isLeadSurrogate(_str.codeUnitAt(_nextIndex)) &&
+              _isTrailSurrogate(_str.codeUnitAt(_nextIndex + 1))) {
+            _nextIndex++;
+          }
+          _nextIndex++;
+        }
+        return true;
+      }
+    }
+    _current = null;
+    _re = null;
+    return false;
+  }
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/schedule_microtask_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/schedule_microtask_patch.dart
new file mode 100644
index 0000000..7fc8317
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/schedule_microtask_patch.dart
@@ -0,0 +1,34 @@
+// 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 "async_patch.dart";
+
+@patch
+class _AsyncRun {
+  @patch
+  static void _scheduleImmediate(void callback()) {
+    if (_ScheduleImmediate._closure == null) {
+      throw new UnsupportedError("Microtasks are not supported");
+    }
+    _ScheduleImmediate._closure(callback);
+  }
+}
+
+typedef void _ScheduleImmediateClosure(void callback());
+
+class _ScheduleImmediate {
+  static _ScheduleImmediateClosure _closure;
+}
+
+@pragma("vm:entry-point", "call")
+void _setScheduleImmediateClosure(_ScheduleImmediateClosure closure) {
+  _ScheduleImmediate._closure = closure;
+}
+
+@pragma("vm:entry-point", "call")
+void _ensureScheduleImmediate() {
+  _AsyncRun._scheduleImmediate(_startMicrotaskLoop);
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/stacktrace.dart b/sdk_nnbd/lib/_internal/vm/lib/stacktrace.dart
new file mode 100644
index 0000000..fc7c633
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/stacktrace.dart
@@ -0,0 +1,13 @@
+// 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 "core_patch.dart";
+
+/// VM internal StackTrace implementation.
+@pragma("vm:entry-point")
+class _StackTrace implements StackTrace {
+  // toString() is overridden on the C++ side.
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/stopwatch_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/stopwatch_patch.dart
new file mode 100644
index 0000000..1aad490
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/stopwatch_patch.dart
@@ -0,0 +1,58 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+@patch
+class Stopwatch {
+  static const _maxInt = 0x7FFFFFFFFFFFFFFF;
+
+  @patch
+  static void _initTicker() {
+    if (_frequency == null) {
+      _frequency = _computeFrequency();
+    }
+  }
+
+  // Returns the current clock tick.
+  @patch
+  static int _now() native "Stopwatch_now";
+
+  // Returns the frequency of clock ticks in Hz.
+  static int _computeFrequency() native "Stopwatch_frequency";
+
+  @patch
+  int get elapsedMicroseconds {
+    int ticks = elapsedTicks;
+    // Special case the more likely frequencies to avoid division,
+    // or divide by a known value.
+    if (_frequency == 1000000000) return ticks ~/ 1000;
+    if (_frequency == 1000000) return ticks;
+    if (_frequency == 1000) return ticks * 1000;
+    if (ticks <= (_maxInt ~/ 1000000)) {
+      return (ticks * 1000000) ~/ _frequency;
+    }
+    // Multiplication would have overflowed.
+    int ticksPerSecond = ticks ~/ _frequency;
+    int remainingTicks = ticks.remainder(_frequency);
+    return ticksPerSecond * 1000000 + (remainingTicks * 1000000) ~/ _frequency;
+  }
+
+  @patch
+  int get elapsedMilliseconds {
+    int ticks = elapsedTicks;
+    if (_frequency == 1000000000) return ticks ~/ 1000000;
+    if (_frequency == 1000000) return ticks ~/ 1000;
+    if (_frequency == 1000) return ticks;
+    if (ticks <= (_maxInt ~/ 1000)) {
+      return (ticks * 1000) ~/ _frequency;
+    }
+    // Multiplication would have overflowed.
+    int ticksPerSecond = ticks ~/ _frequency;
+    int remainingTicks = ticks.remainder(_frequency);
+    return ticksPerSecond * 1000 + (remainingTicks * 1000) ~/ _frequency;
+  }
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/string_buffer_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/string_buffer_patch.dart
new file mode 100644
index 0000000..1403da4
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/string_buffer_patch.dart
@@ -0,0 +1,198 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+@patch
+class StringBuffer {
+  static const int _BUFFER_SIZE = 64;
+  static const int _PARTS_TO_COMPACT = 128;
+  static const int _PARTS_TO_COMPACT_SIZE_LIMIT = _PARTS_TO_COMPACT * 8;
+
+  /**
+   * When strings are written to the string buffer, we add them to a
+   * list of string parts.
+   */
+  List<String> _parts;
+
+  /**
+    * Total number of code units in the string parts. Does not include
+    * the code units added to the buffer.
+    */
+  int _partsCodeUnits = 0;
+
+  /**
+   * To preserve memory, we sometimes compact the parts. This combines
+   * several smaller parts into a single larger part to cut down on the
+   * cost that comes from the per-object memory overhead. We keep track
+   * of the last index where we ended our compaction and the number of
+   * code units added since the last compaction.
+   */
+  int _partsCompactionIndex = 0;
+  int _partsCodeUnitsSinceCompaction = 0;
+
+  /**
+   * The buffer is used to build up a string from code units. It is
+   * used when writing short strings or individual char codes to the
+   * buffer. The buffer is allocated on demand.
+   */
+  Uint16List _buffer;
+  int _bufferPosition = 0;
+
+  /**
+   * Collects the approximate maximal magnitude of the code units added
+   * to the buffer.
+   *
+   * The value of each added code unit is or'ed with this variable, so the
+   * most significant bit set in any code unit is also set in this value.
+   * If below 256, the string in the buffer is a Latin-1 string.
+   */
+  int _bufferCodeUnitMagnitude = 0;
+
+  /// Creates the string buffer with an initial content.
+  @patch
+  StringBuffer([Object content = ""]) {
+    write(content);
+  }
+
+  @patch
+  int get length => _partsCodeUnits + _bufferPosition;
+
+  @patch
+  void write(Object obj) {
+    String str = '$obj';
+    if (str.isEmpty) return;
+    _consumeBuffer();
+    _addPart(str);
+  }
+
+  @patch
+  void writeCharCode(int charCode) {
+    if (charCode <= 0xFFFF) {
+      if (charCode < 0) {
+        throw new RangeError.range(charCode, 0, 0x10FFFF);
+      }
+      _ensureCapacity(1);
+      _buffer[_bufferPosition++] = charCode;
+      _bufferCodeUnitMagnitude |= charCode;
+    } else {
+      if (charCode > 0x10FFFF) {
+        throw new RangeError.range(charCode, 0, 0x10FFFF);
+      }
+      _ensureCapacity(2);
+      int bits = charCode - 0x10000;
+      _buffer[_bufferPosition++] = 0xD800 | (bits >> 10);
+      _buffer[_bufferPosition++] = 0xDC00 | (bits & 0x3FF);
+      _bufferCodeUnitMagnitude |= 0xFFFF;
+    }
+  }
+
+  @patch
+  void writeAll(Iterable objects, [String separator = ""]) {
+    Iterator iterator = objects.iterator;
+    if (!iterator.moveNext()) return;
+    if (separator.isEmpty) {
+      do {
+        write(iterator.current);
+      } while (iterator.moveNext());
+    } else {
+      write(iterator.current);
+      while (iterator.moveNext()) {
+        write(separator);
+        write(iterator.current);
+      }
+    }
+  }
+
+  @patch
+  void writeln([Object obj = ""]) {
+    write(obj);
+    write("\n");
+  }
+
+  /** Makes the buffer empty. */
+  @patch
+  void clear() {
+    _parts = null;
+    _partsCodeUnits = _bufferPosition = _bufferCodeUnitMagnitude = 0;
+  }
+
+  /** Returns the contents of buffer as a string. */
+  @patch
+  String toString() {
+    _consumeBuffer();
+    return (_partsCodeUnits == 0)
+        ? ""
+        : _StringBase._concatRange(_parts, 0, _parts.length);
+  }
+
+  /** Ensures that the buffer has enough capacity to add n code units. */
+  void _ensureCapacity(int n) {
+    if (_buffer == null) {
+      _buffer = new Uint16List(_BUFFER_SIZE);
+    } else if (_bufferPosition + n > _buffer.length) {
+      _consumeBuffer();
+    }
+  }
+
+  /**
+   * Consumes the content of the buffer by turning it into a string
+   * and adding it as a part. After calling this the buffer position
+   * will be reset to zero.
+   */
+  void _consumeBuffer() {
+    if (_bufferPosition == 0) return;
+    bool isLatin1 = _bufferCodeUnitMagnitude <= 0xFF;
+    String str = _create(_buffer, _bufferPosition, isLatin1);
+    _bufferPosition = _bufferCodeUnitMagnitude = 0;
+    _addPart(str);
+  }
+
+  /**
+   * Adds a new part to this string buffer and keeps track of how
+   * many code units are contained in the parts.
+   */
+  void _addPart(String str) {
+    int length = str.length;
+    _partsCodeUnits += length;
+    _partsCodeUnitsSinceCompaction += length;
+
+    if (_parts == null) {
+      // Empirically this is a good capacity to minimize total bytes allocated.
+      _parts = new _GrowableList.withCapacity(10)..add(str);
+    } else {
+      _parts.add(str);
+      int partsSinceCompaction = _parts.length - _partsCompactionIndex;
+      if (partsSinceCompaction == _PARTS_TO_COMPACT) {
+        _compact();
+      }
+    }
+  }
+
+  /**
+   * Compacts the last N parts if their average size allows us to save a
+   * lot of memory by turning them all into a single part.
+   */
+  void _compact() {
+    if (_partsCodeUnitsSinceCompaction < _PARTS_TO_COMPACT_SIZE_LIMIT) {
+      String compacted = _StringBase._concatRange(
+          _parts,
+          _partsCompactionIndex, // Start
+          _partsCompactionIndex + _PARTS_TO_COMPACT // End
+          );
+      _parts.length = _parts.length - _PARTS_TO_COMPACT;
+      _parts.add(compacted);
+    }
+    _partsCodeUnitsSinceCompaction = 0;
+    _partsCompactionIndex = _parts.length;
+  }
+
+  /**
+   * Create a [String] from the UFT-16 code units in buffer.
+   */
+  static String _create(Uint16List buffer, int length, bool isLatin1)
+      native "StringBuffer_createStringFromUint16Array";
+}
diff --git a/runtime/lib/string_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/string_patch.dart
similarity index 98%
rename from runtime/lib/string_patch.dart
rename to sdk_nnbd/lib/_internal/vm/lib/string_patch.dart
index c08bd49..cc3dc07 100644
--- a/runtime/lib/string_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/string_patch.dart
@@ -2,6 +2,8 @@
 // for details. All 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 "core_patch.dart";
 
 const int _maxAscii = 0x7f;
@@ -948,7 +950,9 @@
 
 @pragma("vm:entry-point")
 class _OneByteString extends _StringBase {
-  factory _OneByteString._uninstantiable() { throw "Unreachable"; }
+  factory _OneByteString._uninstantiable() {
+    throw "Unreachable";
+  }
 
   @pragma("vm:exact-result-type", "dart:core#_Smi")
   int get hashCode native "String_getHashCode";
@@ -1254,7 +1258,9 @@
 
 @pragma("vm:entry-point")
 class _TwoByteString extends _StringBase {
-  factory _TwoByteString._uninstantiable() { throw "Unreachable"; }
+  factory _TwoByteString._uninstantiable() {
+    throw "Unreachable";
+  }
 
   static String _allocateFromTwoByteList(List<int> list, int start, int end)
       native "TwoByteString_allocateFromTwoByteList";
@@ -1274,7 +1280,9 @@
 
 @pragma("vm:entry-point")
 class _ExternalOneByteString extends _StringBase {
-  factory _ExternalOneByteString._uninstantiable() { throw "Unreachable"; }
+  factory _ExternalOneByteString._uninstantiable() {
+    throw "Unreachable";
+  }
 
   bool _isWhitespace(int codeUnit) {
     return _StringBase._isOneByteWhitespace(codeUnit);
@@ -1290,7 +1298,9 @@
 
 @pragma("vm:entry-point")
 class _ExternalTwoByteString extends _StringBase {
-  factory _ExternalTwoByteString._uninstantiable() { throw "Unreachable"; }
+  factory _ExternalTwoByteString._uninstantiable() {
+    throw "Unreachable";
+  }
 
   bool _isWhitespace(int codeUnit) {
     return _StringBase._isTwoByteWhitespace(codeUnit);
diff --git a/sdk_nnbd/lib/_internal/vm/lib/symbol_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/symbol_patch.dart
new file mode 100644
index 0000000..eb7a0f8
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/symbol_patch.dart
@@ -0,0 +1,62 @@
+// 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 "internal_patch.dart";
+
+@patch
+class Symbol {
+  @patch
+  const Symbol(String name) : this._name = name;
+
+  @patch
+  toString() => 'Symbol("${computeUnmangledName(this)}")';
+
+  @patch
+  static String computeUnmangledName(Symbol symbol) {
+    String string = Symbol.getName(symbol);
+
+    // get:foo -> foo
+    // set:foo -> foo=
+    // get:_foo@xxx -> _foo
+    // set:_foo@xxx -> _foo=
+    // Class._constructor@xxx -> Class._constructor
+    // _Class@xxx._constructor@xxx -> _Class._constructor
+    // lib._S@xxx with lib._M1@xxx, lib._M2@xxx -> lib._S with lib._M1, lib._M2
+    StringBuffer result = new StringBuffer();
+    bool add_setter_suffix = false;
+    var pos = 0;
+    if (string.length >= 4 && string[3] == ':') {
+      // Drop 'get:' or 'set:' prefix.
+      pos = 4;
+      if (string[0] == 's') {
+        add_setter_suffix = true;
+      }
+    }
+    // Skip everything between AT and PERIOD, SPACE, COMMA or END
+    bool skip = false;
+    for (; pos < string.length; pos++) {
+      var char = string[pos];
+      if (char == '@') {
+        skip = true;
+      } else if (char == '.' || char == ' ' || char == ',') {
+        skip = false;
+      }
+      if (!skip) {
+        result.write(char);
+      }
+    }
+    if (add_setter_suffix) {
+      result.write('=');
+    }
+    return result.toString();
+  }
+
+  @patch
+  int get hashCode {
+    const arbitraryPrime = 664597;
+    return 0x1fffffff & (arbitraryPrime * _name.hashCode);
+  }
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/timeline.dart b/sdk_nnbd/lib/_internal/vm/lib/timeline.dart
new file mode 100644
index 0000000..9b3ed42
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/timeline.dart
@@ -0,0 +1,35 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "developer.dart";
+
+@patch
+bool _isDartStreamEnabled() native "Timeline_isDartStreamEnabled";
+
+@patch
+int _getTraceClock() native "Timeline_getTraceClock";
+
+@patch
+int _getThreadCpuClock() native "Timeline_getThreadCpuClock";
+
+@patch
+int _getNextAsyncId() native "Timeline_getNextAsyncId";
+
+@patch
+void _reportTaskEvent(int start, int taskId, String phase, String category,
+    String name, String argumentsAsJson) native "Timeline_reportTaskEvent";
+
+@patch
+void _reportCompleteEvent(int start, int startCpu, String category, String name,
+    String argumentsAsJson) native "Timeline_reportCompleteEvent";
+
+@patch
+void _reportFlowEvent(int start, int startCpu, String category, String name,
+    int type, int id, String argumentsAsJson) native "Timeline_reportFlowEvent";
+
+@patch
+void _reportInstantEvent(int start, String category, String name,
+    String argumentsAsJson) native "Timeline_reportInstantEvent";
diff --git a/sdk_nnbd/lib/_internal/vm/lib/timer_impl.dart b/sdk_nnbd/lib/_internal/vm/lib/timer_impl.dart
new file mode 100644
index 0000000..fe80645
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/timer_impl.dart
@@ -0,0 +1,471 @@
+// 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 "isolate_patch.dart";
+
+// Timer heap implemented as a array-based binary heap[0].
+// This allows for O(1) `first`, O(log(n)) `remove`/`removeFirst` and O(log(n))
+// `add`.
+//
+// To ensure the timers are ordered by insertion time, the _Timer class has a
+// `_id` field set when added to the heap.
+//
+// [0] http://en.wikipedia.org/wiki/Binary_heap
+class _TimerHeap {
+  List<_Timer> _list;
+  int _used = 0;
+
+  _TimerHeap([int initSize = 7]) : _list = new List<_Timer>(initSize);
+
+  bool get isEmpty => _used == 0;
+
+  _Timer get first => _list[0];
+
+  bool isFirst(_Timer timer) => timer._indexOrNext == 0;
+
+  void add(_Timer timer) {
+    if (_used == _list.length) {
+      _resize();
+    }
+    timer._indexOrNext = _used++;
+    _list[timer._indexOrNext] = timer;
+    _bubbleUp(timer);
+  }
+
+  _Timer removeFirst() {
+    var f = first;
+    remove(f);
+    return f;
+  }
+
+  void remove(_Timer timer) {
+    _used--;
+    if (isEmpty) {
+      _list[0] = null;
+      timer._indexOrNext = null;
+      return;
+    }
+    var last = _list[_used];
+    if (!identical(last, timer)) {
+      last._indexOrNext = timer._indexOrNext;
+      _list[last._indexOrNext] = last;
+      if (last._compareTo(timer) < 0) {
+        _bubbleUp(last);
+      } else {
+        _bubbleDown(last);
+      }
+    }
+    _list[_used] = null;
+    timer._indexOrNext = null;
+  }
+
+  void _resize() {
+    var newList = new List<_Timer>(_list.length * 2 + 1);
+    newList.setRange(0, _used, _list);
+    _list = newList;
+  }
+
+  void _bubbleUp(_Timer timer) {
+    while (!isFirst(timer)) {
+      Timer parent = _parent(timer);
+      if (timer._compareTo(parent) < 0) {
+        _swap(timer, parent);
+      } else {
+        break;
+      }
+    }
+  }
+
+  void _bubbleDown(_Timer timer) {
+    while (true) {
+      int leftIndex = _leftChildIndex(timer._indexOrNext);
+      int rightIndex = _rightChildIndex(timer._indexOrNext);
+      _Timer newest = timer;
+      if (leftIndex < _used && _list[leftIndex]._compareTo(newest) < 0) {
+        newest = _list[leftIndex];
+      }
+      if (rightIndex < _used && _list[rightIndex]._compareTo(newest) < 0) {
+        newest = _list[rightIndex];
+      }
+      if (identical(newest, timer)) {
+        // We are where we should be, break.
+        break;
+      }
+      _swap(newest, timer);
+    }
+  }
+
+  void _swap(_Timer first, _Timer second) {
+    int tmp = first._indexOrNext;
+    first._indexOrNext = second._indexOrNext;
+    second._indexOrNext = tmp;
+    _list[first._indexOrNext] = first;
+    _list[second._indexOrNext] = second;
+  }
+
+  Timer _parent(_Timer timer) => _list[_parentIndex(timer._indexOrNext)];
+  Timer _leftChild(_Timer timer) => _list[_leftChildIndex(timer._indexOrNext)];
+  Timer _rightChild(_Timer timer) =>
+      _list[_rightChildIndex(timer._indexOrNext)];
+
+  static int _parentIndex(int index) => (index - 1) ~/ 2;
+  static int _leftChildIndex(int index) => 2 * index + 1;
+  static int _rightChildIndex(int index) => 2 * index + 2;
+}
+
+class _Timer implements Timer {
+  // Cancels the timer in the event handler.
+  static const _NO_TIMER = -1;
+
+  // We distinguish what kind of message arrived based on the value being sent.
+  static const _ZERO_EVENT = 1;
+  static const _TIMEOUT_EVENT = null;
+
+  // Timers are ordered by wakeup time. Timers with a timeout value of > 0 do
+  // end up on the TimerHeap. Timers with a timeout of 0 are queued in a list.
+  static final _heap = new _TimerHeap();
+  static _Timer _firstZeroTimer;
+  static _Timer _lastZeroTimer;
+
+  // We use an id to be able to sort timers with the same expiration time.
+  // ids are recycled after ID_MASK enqueues or when the timer queue is empty.
+  static const _ID_MASK = 0x1fffffff;
+  static int _idCount = 0;
+
+  static RawReceivePort _receivePort;
+  static SendPort _sendPort;
+  static int _scheduledWakeupTime;
+
+  static bool _handlingCallbacks = false;
+
+  Function _callback; // Closure to call when timer fires. null if canceled.
+  int _wakeupTime; // Expiration time.
+  final int _milliSeconds; // Duration specified at creation.
+  final bool _repeating; // Indicates periodic timers.
+  var _indexOrNext; // Index if part of the TimerHeap, link otherwise.
+  int _id; // Incrementing id to enable sorting of timers with same expiry.
+
+  int _tick = 0; // Backing for [tick],
+
+  // Get the next available id. We accept collisions and reordering when the
+  // _idCount overflows and the timers expire at the same millisecond.
+  static int _nextId() {
+    var result = _idCount;
+    _idCount = (_idCount + 1) & _ID_MASK;
+    return result;
+  }
+
+  _Timer._internal(
+      this._callback, this._wakeupTime, this._milliSeconds, this._repeating)
+      : _id = _nextId();
+
+  static Timer _createTimer(
+      void callback(Timer timer), int milliSeconds, bool repeating) {
+    // Negative timeouts are treated as if 0 timeout.
+    if (milliSeconds < 0) {
+      milliSeconds = 0;
+    }
+    // Add one because DateTime.now() is assumed to round down
+    // to nearest millisecond, not up, so that time + duration is before
+    // duration milliseconds from now. Using microsecond timers like
+    // Stopwatch allows detecting that the timer fires early.
+    int now = VMLibraryHooks.timerMillisecondClock();
+    int wakeupTime = (milliSeconds == 0) ? now : (now + 1 + milliSeconds);
+
+    _Timer timer =
+        new _Timer._internal(callback, wakeupTime, milliSeconds, repeating);
+    // Enqueue this newly created timer in the appropriate structure and
+    // notify if necessary.
+    timer._enqueue();
+    return timer;
+  }
+
+  factory _Timer(int milliSeconds, void callback(Timer timer)) {
+    return _createTimer(callback, milliSeconds, false);
+  }
+
+  factory _Timer.periodic(int milliSeconds, void callback(Timer timer)) {
+    return _createTimer(callback, milliSeconds, true);
+  }
+
+  bool get _isInHeap => _indexOrNext is int;
+
+  int _compareTo(_Timer other) {
+    int c = _wakeupTime - other._wakeupTime;
+    if (c != 0) return c;
+    return _id - other._id;
+  }
+
+  bool get isActive => _callback != null;
+
+  int get tick => _tick;
+
+  // Cancels a set timer. The timer is removed from the timer heap if it is a
+  // non-zero timer. Zero timers are kept in the list as they need to consume
+  // the corresponding pending message.
+  void cancel() {
+    _callback = null;
+    // Only heap timers are really removed. Zero timers need to consume their
+    // corresponding wakeup message so they are left in the queue.
+    if (!_isInHeap) return;
+    bool update = _heap.isFirst(this);
+    _heap.remove(this);
+    if (update) {
+      _notifyEventHandler();
+    }
+  }
+
+  void _advanceWakeupTime() {
+    // Recalculate the next wakeup time. For repeating timers with a 0 timeout
+    // the next wakeup time is now.
+    _id = _nextId();
+    if (_milliSeconds > 0) {
+      _wakeupTime += _milliSeconds;
+    } else {
+      _wakeupTime = VMLibraryHooks.timerMillisecondClock();
+    }
+  }
+
+  // Adds a timer to the heap or timer list. Timers with the same wakeup time
+  // are enqueued in order and notified in FIFO order.
+  void _enqueue() {
+    if (_milliSeconds == 0) {
+      if (_firstZeroTimer == null) {
+        _lastZeroTimer = this;
+        _firstZeroTimer = this;
+      } else {
+        _lastZeroTimer._indexOrNext = this;
+        _lastZeroTimer = this;
+      }
+      // Every zero timer gets its own event.
+      _notifyZeroHandler();
+    } else {
+      _heap.add(this);
+      if (_heap.isFirst(this)) {
+        _notifyEventHandler();
+      }
+    }
+  }
+
+  // Enqueue one message for each zero timer. To be able to distinguish from
+  // EventHandler messages we send a _ZERO_EVENT instead of a _TIMEOUT_EVENT.
+  static void _notifyZeroHandler() {
+    if (_sendPort == null) {
+      _createTimerHandler();
+    }
+    _sendPort.send(_ZERO_EVENT);
+  }
+
+  // Handle the notification of a zero timer. Make sure to also execute non-zero
+  // timers with a lower expiration time.
+  static List _queueFromZeroEvent() {
+    var pendingTimers = new List();
+    assert(_firstZeroTimer != null);
+    // Collect pending timers from the timer heap that have an expiration prior
+    // to the currently notified zero timer.
+    var timer;
+    while (!_heap.isEmpty && (_heap.first._compareTo(_firstZeroTimer) < 0)) {
+      timer = _heap.removeFirst();
+      pendingTimers.add(timer);
+    }
+    // Append the first zero timer to the pending timers.
+    timer = _firstZeroTimer;
+    _firstZeroTimer = timer._indexOrNext;
+    timer._indexOrNext = null;
+    pendingTimers.add(timer);
+    return pendingTimers;
+  }
+
+  static void _notifyEventHandler() {
+    if (_handlingCallbacks) {
+      // While we are already handling callbacks we will not notify the event
+      // handler. _handleTimeout will call _notifyEventHandler once all pending
+      // timers are processed.
+      return;
+    }
+
+    // If there are no pending timers. Close down the receive port.
+    if ((_firstZeroTimer == null) && _heap.isEmpty) {
+      // No pending timers: Close the receive port and let the event handler
+      // know.
+      if (_sendPort != null) {
+        _cancelWakeup();
+        _shutdownTimerHandler();
+      }
+      return;
+    } else if (_heap.isEmpty) {
+      // Only zero timers are left. Cancel any scheduled wakeups.
+      _cancelWakeup();
+      return;
+    }
+
+    // Only send a message if the requested wakeup time differs from the
+    // already scheduled wakeup time.
+    var wakeupTime = _heap.first._wakeupTime;
+    if ((_scheduledWakeupTime == null) ||
+        (wakeupTime != _scheduledWakeupTime)) {
+      _scheduleWakeup(wakeupTime);
+    }
+  }
+
+  static List _queueFromTimeoutEvent() {
+    var pendingTimers = new List();
+    if (_firstZeroTimer != null) {
+      // Collect pending timers from the timer heap that have an expiration
+      // prior to the next zero timer.
+      // By definition the first zero timer has been scheduled before the
+      // current time, meaning all timers which are "less than" the first zero
+      // timer are expired. The first zero timer will be dispatched when its
+      // corresponding message is delivered.
+      var timer;
+      while (!_heap.isEmpty && (_heap.first._compareTo(_firstZeroTimer) < 0)) {
+        timer = _heap.removeFirst();
+        pendingTimers.add(timer);
+      }
+    } else {
+      // Collect pending timers from the timer heap which have expired at this
+      // time.
+      var currentTime = VMLibraryHooks.timerMillisecondClock();
+      var timer;
+      while (!_heap.isEmpty && (_heap.first._wakeupTime <= currentTime)) {
+        timer = _heap.removeFirst();
+        pendingTimers.add(timer);
+      }
+    }
+    return pendingTimers;
+  }
+
+  static void _runTimers(List pendingTimers) {
+    // If there are no pending timers currently reset the id space before we
+    // have a chance to enqueue new timers.
+    if (_heap.isEmpty && (_firstZeroTimer == null)) {
+      _idCount = 0;
+    }
+
+    // Fast exit if no pending timers.
+    if (pendingTimers.length == 0) {
+      return;
+    }
+
+    // Trigger all of the pending timers. New timers added as part of the
+    // callbacks will be enqueued now and notified in the next spin at the
+    // earliest.
+    _handlingCallbacks = true;
+    var i = 0;
+    try {
+      for (; i < pendingTimers.length; i++) {
+        // Next pending timer.
+        var timer = pendingTimers[i];
+        timer._indexOrNext = null;
+
+        // One of the timers in the pending_timers list can cancel
+        // one of the later timers which will set the callback to
+        // null. Or the pending zero timer has been canceled earlier.
+        if (timer._callback != null) {
+          var callback = timer._callback;
+          if (!timer._repeating) {
+            // Mark timer as inactive.
+            timer._callback = null;
+          } else if (timer._milliSeconds > 0) {
+            var ms = timer._milliSeconds;
+            int overdue =
+                VMLibraryHooks.timerMillisecondClock() - timer._wakeupTime;
+            if (overdue > ms) {
+              int missedTicks = overdue ~/ ms;
+              timer._wakeupTime += missedTicks * ms;
+              timer._tick += missedTicks;
+            }
+          }
+          timer._tick += 1;
+
+          callback(timer);
+          // Re-insert repeating timer if not canceled.
+          if (timer._repeating && (timer._callback != null)) {
+            timer._advanceWakeupTime();
+            timer._enqueue();
+          }
+          // Execute pending micro tasks.
+          var immediateCallback = _removePendingImmediateCallback();
+          if (immediateCallback != null) {
+            immediateCallback();
+          }
+        }
+      }
+    } finally {
+      _handlingCallbacks = false;
+      // Re-queue timers we didn't get to.
+      for (i++; i < pendingTimers.length; i++) {
+        var timer = pendingTimers[i];
+        timer._enqueue();
+      }
+      _notifyEventHandler();
+    }
+  }
+
+  static void _handleMessage(msg) {
+    var pendingTimers;
+    if (msg == _ZERO_EVENT) {
+      pendingTimers = _queueFromZeroEvent();
+      assert(pendingTimers.length > 0);
+    } else {
+      assert(msg == _TIMEOUT_EVENT);
+      _scheduledWakeupTime = null; // Consumed the last scheduled wakeup now.
+      pendingTimers = _queueFromTimeoutEvent();
+    }
+    _runTimers(pendingTimers);
+    // Notify the event handler or shutdown the port if no more pending
+    // timers are present.
+    _notifyEventHandler();
+  }
+
+  // Tell the event handler to wake this isolate at a specific time.
+  static void _scheduleWakeup(int wakeupTime) {
+    if (_sendPort == null) {
+      _createTimerHandler();
+    }
+    VMLibraryHooks.eventHandlerSendData(null, _sendPort, wakeupTime);
+    _scheduledWakeupTime = wakeupTime;
+  }
+
+  // Cancel pending wakeups in the event handler.
+  static void _cancelWakeup() {
+    if (_sendPort != null) {
+      VMLibraryHooks.eventHandlerSendData(null, _sendPort, _NO_TIMER);
+      _scheduledWakeupTime = null;
+    }
+  }
+
+  // Create a receive port and register a message handler for the timer
+  // events.
+  static void _createTimerHandler() {
+    assert(_receivePort == null);
+    assert(_sendPort == null);
+    _receivePort = new RawReceivePort(_handleMessage);
+    _sendPort = _receivePort.sendPort;
+    _scheduledWakeupTime = null;
+  }
+
+  static void _shutdownTimerHandler() {
+    _receivePort.close();
+    _receivePort = null;
+    _sendPort = null;
+    _scheduledWakeupTime = null;
+  }
+
+  // The Timer factory registered with the dart:async library by the embedder.
+  static Timer _factory(
+      int milliSeconds, void callback(Timer timer), bool repeating) {
+    if (repeating) {
+      return new _Timer.periodic(milliSeconds, callback);
+    }
+    return new _Timer(milliSeconds, callback);
+  }
+}
+
+@pragma("vm:entry-point", "call")
+_setupHooks() {
+  VMLibraryHooks.timerFactory = _Timer._factory;
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/timer_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/timer_patch.dart
new file mode 100644
index 0000000..96c9c78b
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/timer_patch.dart
@@ -0,0 +1,46 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "async_patch.dart";
+
+@patch
+class Timer {
+  @patch
+  static Timer _createTimer(Duration duration, void callback()) {
+    // TODO(iposva): Remove _TimerFactory and use VMLibraryHooks exclusively.
+    if (_TimerFactory._factory == null) {
+      _TimerFactory._factory = VMLibraryHooks.timerFactory;
+    }
+    if (_TimerFactory._factory == null) {
+      throw new UnsupportedError("Timer interface not supported.");
+    }
+    int milliseconds = duration.inMilliseconds;
+    if (milliseconds < 0) milliseconds = 0;
+    return _TimerFactory._factory(milliseconds, (_) {
+      callback();
+    }, false);
+  }
+
+  @patch
+  static Timer _createPeriodicTimer(
+      Duration duration, void callback(Timer timer)) {
+    // TODO(iposva): Remove _TimerFactory and use VMLibraryHooks exclusively.
+    _TimerFactory._factory ??= VMLibraryHooks.timerFactory;
+    if (_TimerFactory._factory == null) {
+      throw new UnsupportedError("Timer interface not supported.");
+    }
+    int milliseconds = duration.inMilliseconds;
+    if (milliseconds < 0) milliseconds = 0;
+    return _TimerFactory._factory(milliseconds, callback, true);
+  }
+}
+
+typedef Timer _TimerFactoryClosure(
+    int milliseconds, void callback(Timer timer), bool repeating);
+
+class _TimerFactory {
+  static _TimerFactoryClosure _factory;
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/type_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/type_patch.dart
new file mode 100644
index 0000000..a4af411
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/type_patch.dart
@@ -0,0 +1,41 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+// These Dart classes correspond to the VM internal implementation classes.
+
+// Equivalent of RawAbstractType.
+abstract class _AbstractType implements Type {
+  String toString() native "AbstractType_toString";
+}
+
+// Equivalent of RawType.
+@pragma("vm:entry-point")
+class _Type extends _AbstractType {
+  factory _Type._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  int get hashCode native "Type_getHashCode";
+}
+
+// Equivalent of RawTypeRef.
+@pragma("vm:entry-point")
+class _TypeRef extends _AbstractType {
+  factory _TypeRef._uninstantiable() {
+    throw "Unreachable";
+  }
+}
+
+// Equivalent of RawTypeParameter.
+@pragma("vm:entry-point")
+class _TypeParameter extends _AbstractType {
+  factory _TypeParameter._uninstantiable() {
+    throw "Unreachable";
+  }
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/typed_data_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/typed_data_patch.dart
new file mode 100644
index 0000000..8443c16
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/typed_data_patch.dart
@@ -0,0 +1,4640 @@
+// 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
+
+/// 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
+/// shared front end and simply use parts.
+
+import "dart:_internal"
+    show
+        ClassID,
+        CodeUnits,
+        ExpandIterable,
+        FollowedByIterable,
+        IterableElementError,
+        ListMapView,
+        Lists,
+        MappedIterable,
+        MappedIterable,
+        ReversedListIterable,
+        SkipWhileIterable,
+        Sort,
+        SubListIterable,
+        TakeWhileIterable,
+        WhereIterable,
+        WhereTypeIterable,
+        patch;
+
+import "dart:collection" show ListBase;
+
+import 'dart:math' show Random;
+
+/// There are no parts in patch library:
+
+@patch
+class ByteData implements TypedData {
+  @patch
+  @pragma("vm:entry-point")
+  factory ByteData(int length) {
+    final list = new Uint8List(length) as _TypedList;
+    _rangeCheck(list.lengthInBytes, 0, length);
+    return new _ByteDataView._(list, 0, length);
+  }
+
+  // Called directly from C code.
+  @pragma("vm:entry-point")
+  factory ByteData._view(_TypedList typedData, int offsetInBytes, int length) {
+    _rangeCheck(typedData.lengthInBytes, offsetInBytes, length);
+    return new _ByteDataView._(typedData, offsetInBytes, length);
+  }
+}
+
+// Based class for _TypedList that provides common methods for implementing
+// the collection and list interfaces.
+// This class does not extend ListBase<T> since that would add type arguments
+// to instances of _TypeListBase. Instead the subclasses use type specific
+// mixins (like _IntListMixin, _DoubleListMixin) to implement ListBase<T>.
+abstract class _TypedListBase {
+  int get length;
+  int get elementSizeInBytes;
+  int get offsetInBytes;
+  _ByteBuffer get buffer;
+
+  // Method(s) implementing the Collection interface.
+  String join([String separator = ""]) {
+    StringBuffer buffer = new StringBuffer();
+    buffer.writeAll(this as Iterable, separator);
+    return buffer.toString();
+  }
+
+  bool get isEmpty {
+    return this.length == 0;
+  }
+
+  bool get isNotEmpty => !isEmpty;
+
+  // Method(s) implementing the List interface.
+
+  set length(newLength) {
+    throw new UnsupportedError("Cannot resize a fixed-length list");
+  }
+
+  void clear() {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  bool remove(Object element) {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  void removeRange(int start, int end) {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  void replaceRange(int start, int end, Iterable iterable) {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  // Method(s) implementing Object interface.
+  String toString() => ListBase.listToString(this as List);
+
+  // Internal utility methods.
+
+  // Returns true if operation succeeds.
+  // 'fromCid' and 'toCid' may be cid-s of the views and therefore may not
+  // match the cids of 'this' and 'from'.
+  // Uses toCid and fromCid to decide if clamping is necessary.
+  // Element size of toCid and fromCid must match (test at caller).
+  bool _setRange(int startInBytes, int lengthInBytes, _TypedListBase from,
+      int startFromInBytes, int toCid, int fromCid) native "TypedData_setRange";
+}
+
+mixin _IntListMixin implements List<int> {
+  int get elementSizeInBytes;
+  int get offsetInBytes;
+  _ByteBuffer get buffer;
+
+  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+
+  Iterable<int> followedBy(Iterable<int> other) =>
+      new FollowedByIterable<int>.firstEfficient(this, other);
+
+  List<R> cast<R>() => List.castFrom<int, R>(this);
+  void set first(int value) {
+    if (this.length == 0) throw new RangeError.index(0, this);
+    this[0] = value;
+  }
+
+  void set last(int value) {
+    if (this.length == 0) throw new RangeError.index(0, this);
+    this[this.length - 1] = value;
+  }
+
+  int indexWhere(bool test(int element), [int start = 0]) {
+    if (start < 0) start = 0;
+    for (int i = start; i < length; i++) {
+      if (test(this[i])) return i;
+    }
+    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--) {
+      if (test(this[i])) return i;
+    }
+    return -1;
+  }
+
+  List<int> operator +(List<int> other) {
+    int totalLength = this.length + other.length;
+    return <int>[]
+      ..length = totalLength
+      ..setRange(0, this.length, this)
+      ..setRange(this.length, totalLength, other);
+  }
+
+  bool contains(Object element) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      if (this[i] == element) return true;
+    }
+    return false;
+  }
+
+  void shuffle([Random random]) {
+    random ??= new Random();
+    var i = this.length;
+    while (i > 1) {
+      int pos = random.nextInt(i);
+      i -= 1;
+      var tmp = this[i];
+      this[i] = this[pos];
+      this[pos] = tmp;
+    }
+  }
+
+  Iterable<int> where(bool f(int element)) => new WhereIterable<int>(this, f);
+
+  Iterable<int> take(int n) => new SubListIterable<int>(this, 0, n);
+
+  Iterable<int> takeWhile(bool test(int element)) =>
+      new TakeWhileIterable<int>(this, test);
+
+  Iterable<int> skip(int n) => new SubListIterable<int>(this, n, null);
+
+  Iterable<int> skipWhile(bool test(int element)) =>
+      new SkipWhileIterable<int>(this, test);
+
+  Iterable<int> get reversed => new ReversedListIterable<int>(this);
+
+  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);
+  }
+
+  Iterator<int> get iterator => new _TypedListIterator<int>(this);
+
+  List<int> toList({bool growable: true}) {
+    return new List<int>.from(this, growable: growable);
+  }
+
+  Set<int> toSet() {
+    return new Set<int>.from(this);
+  }
+
+  void forEach(void f(int element)) {
+    var len = this.length;
+    for (var i = 0; i < len; i++) {
+      f(this[i]);
+    }
+  }
+
+  int reduce(int combine(int value, int element)) {
+    var len = this.length;
+    if (len == 0) throw IterableElementError.noElement();
+    var value = this[0];
+    for (var i = 1; i < len; ++i) {
+      value = combine(value, this[i]);
+    }
+    return value;
+  }
+
+  T fold<T>(T initialValue, T combine(T initialValue, int element)) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      initialValue = combine(initialValue, this[i]);
+    }
+    return initialValue;
+  }
+
+  Iterable<T> map<T>(T f(int element)) => new MappedIterable<int, T>(this, f);
+
+  Iterable<T> expand<T>(Iterable<T> f(int element)) =>
+      new ExpandIterable<int, T>(this, f);
+
+  bool every(bool f(int element)) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      if (!f(this[i])) return false;
+    }
+    return true;
+  }
+
+  bool any(bool f(int element)) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      if (f(this[i])) return true;
+    }
+    return false;
+  }
+
+  int firstWhere(bool test(int element), {int orElse()}) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      var element = this[i];
+      if (test(element)) return element;
+    }
+    if (orElse != null) return orElse();
+    throw IterableElementError.noElement();
+  }
+
+  int lastWhere(bool test(int element), {int orElse()}) {
+    var len = this.length;
+    for (var i = len - 1; i >= 0; --i) {
+      var element = this[i];
+      if (test(element)) {
+        return element;
+      }
+    }
+    if (orElse != null) return orElse();
+    throw IterableElementError.noElement();
+  }
+
+  int singleWhere(bool test(int element), {int orElse()}) {
+    var result = null;
+    bool foundMatching = false;
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      var element = this[i];
+      if (test(element)) {
+        if (foundMatching) {
+          throw IterableElementError.tooMany();
+        }
+        result = element;
+        foundMatching = true;
+      }
+    }
+    if (foundMatching) return result;
+    if (orElse != null) return orElse();
+    throw IterableElementError.noElement();
+  }
+
+  int elementAt(int index) {
+    return this[index];
+  }
+
+  void add(int value) {
+    throw new UnsupportedError("Cannot add to a fixed-length list");
+  }
+
+  void addAll(Iterable<int> value) {
+    throw new UnsupportedError("Cannot add to a fixed-length list");
+  }
+
+  void insert(int index, int value) {
+    throw new UnsupportedError("Cannot insert into a fixed-length list");
+  }
+
+  void insertAll(int index, Iterable<int> values) {
+    throw new UnsupportedError("Cannot insert into a fixed-length list");
+  }
+
+  void sort([int compare(int a, int b)]) {
+    Sort.sort(this, compare ?? Comparable.compare);
+  }
+
+  int indexOf(int element, [int start = 0]) {
+    if (start >= this.length) {
+      return -1;
+    } else if (start < 0) {
+      start = 0;
+    }
+    for (int i = start; i < this.length; i++) {
+      if (this[i] == element) return i;
+    }
+    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--) {
+      if (this[i] == element) return i;
+    }
+    return -1;
+  }
+
+  int removeLast() {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  int removeAt(int index) {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  void removeWhere(bool test(int element)) {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  void retainWhere(bool test(int element)) {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  int get first {
+    if (length > 0) return this[0];
+    throw IterableElementError.noElement();
+  }
+
+  int get last {
+    if (length > 0) return this[length - 1];
+    throw IterableElementError.noElement();
+  }
+
+  int get single {
+    if (length == 1) return this[0];
+    if (length == 0) throw IterableElementError.noElement();
+    throw IterableElementError.tooMany();
+  }
+
+  void setAll(int index, Iterable<int> iterable) {
+    final end = iterable.length + index;
+    setRange(index, end, iterable);
+  }
+
+  void fillRange(int start, int end, [int fillValue]) {
+    RangeError.checkValidRange(start, end, this.length);
+    for (var i = start; i < end; ++i) {
+      this[i] = fillValue;
+    }
+  }
+}
+
+mixin _TypedIntListMixin<SpawnedType extends List<int>> on _IntListMixin
+    implements List<int> {
+  SpawnedType _createList(int length);
+
+  void setRange(int start, int end, Iterable<int> from, [int skipCount = 0]) {
+    // Check ranges.
+    if (0 > start || start > end || end > length) {
+      RangeError.checkValidRange(start, end, length); // Always throws.
+      assert(false);
+    }
+    if (skipCount < 0) {
+      throw RangeError.range(skipCount, 0, null, "skipCount");
+    }
+
+    final count = end - start;
+    if ((from.length - skipCount) < count) {
+      throw IterableElementError.tooFew();
+    }
+
+    if (count == 0) return;
+
+    if (from is _TypedListBase) {
+      // Note: _TypedListBase is not related to Iterable<int> so there is
+      // no promotion here.
+      final fromAsTypedList = from as _TypedListBase;
+      if (this.elementSizeInBytes == fromAsTypedList.elementSizeInBytes) {
+        if ((count < 10) && (fromAsTypedList.buffer != this.buffer)) {
+          Lists.copy(from as List<int>, skipCount, this, start, count);
+          return;
+        } else if (this.buffer._data._setRange(
+            start * elementSizeInBytes + this.offsetInBytes,
+            count * elementSizeInBytes,
+            fromAsTypedList.buffer._data,
+            skipCount * elementSizeInBytes + fromAsTypedList.offsetInBytes,
+            ClassID.getID(this),
+            ClassID.getID(from))) {
+          return;
+        }
+      } else if (fromAsTypedList.buffer == this.buffer) {
+        // Different element sizes, but same buffer means that we need
+        // an intermediate structure.
+        // TODO(srdjan): Optimize to skip copying if the range does not overlap.
+        final fromAsList = from as List<int>;
+        final tempBuffer = _createList(count);
+        for (var i = 0; i < count; i++) {
+          tempBuffer[i] = fromAsList[skipCount + i];
+        }
+        for (var i = start; i < end; i++) {
+          this[i] = tempBuffer[i - start];
+        }
+        return;
+      }
+    }
+
+    List otherList;
+    int otherStart;
+    if (from is List<int>) {
+      otherList = from;
+      otherStart = skipCount;
+    } else {
+      otherList = from.skip(skipCount).toList(growable: false);
+      otherStart = 0;
+    }
+    if (otherStart + count > otherList.length) {
+      throw IterableElementError.tooFew();
+    }
+    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 result = _createList(length);
+    result.setRange(0, length, this, start);
+    return result;
+  }
+}
+
+mixin _DoubleListMixin implements List<double> {
+  int get elementSizeInBytes;
+  int get offsetInBytes;
+  _ByteBuffer get buffer;
+
+  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+
+  Iterable<double> followedBy(Iterable<double> other) =>
+      new FollowedByIterable<double>.firstEfficient(this, other);
+
+  List<R> cast<R>() => List.castFrom<double, R>(this);
+  void set first(double value) {
+    if (this.length == 0) throw new RangeError.index(0, this);
+    this[0] = value;
+  }
+
+  void set last(double value) {
+    if (this.length == 0) throw new RangeError.index(0, this);
+    this[this.length - 1] = value;
+  }
+
+  int indexWhere(bool test(double element), [int start = 0]) {
+    if (start < 0) start = 0;
+    for (int i = start; i < length; i++) {
+      if (test(this[i])) return i;
+    }
+    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--) {
+      if (test(this[i])) return i;
+    }
+    return -1;
+  }
+
+  List<double> operator +(List<double> other) {
+    int totalLength = this.length + other.length;
+    return <double>[]
+      ..length = totalLength
+      ..setRange(0, this.length, this)
+      ..setRange(this.length, totalLength, other);
+  }
+
+  bool contains(Object element) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      if (this[i] == element) return true;
+    }
+    return false;
+  }
+
+  void shuffle([Random random]) {
+    random ??= new Random();
+    var i = this.length;
+    while (i > 1) {
+      int pos = random.nextInt(i);
+      i -= 1;
+      var tmp = this[i];
+      this[i] = this[pos];
+      this[pos] = tmp;
+    }
+  }
+
+  Iterable<double> where(bool f(double element)) =>
+      new WhereIterable<double>(this, f);
+
+  Iterable<double> take(int n) => new SubListIterable<double>(this, 0, n);
+
+  Iterable<double> takeWhile(bool test(double element)) =>
+      new TakeWhileIterable<double>(this, test);
+
+  Iterable<double> skip(int n) => new SubListIterable<double>(this, n, null);
+
+  Iterable<double> skipWhile(bool test(double element)) =>
+      new SkipWhileIterable<double>(this, test);
+
+  Iterable<double> get reversed => new ReversedListIterable<double>(this);
+
+  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);
+  }
+
+  Iterator<double> get iterator => new _TypedListIterator<double>(this);
+
+  List<double> toList({bool growable: true}) {
+    return new List<double>.from(this, growable: growable);
+  }
+
+  Set<double> toSet() {
+    return new Set<double>.from(this);
+  }
+
+  void forEach(void f(double element)) {
+    var len = this.length;
+    for (var i = 0; i < len; i++) {
+      f(this[i]);
+    }
+  }
+
+  double reduce(double combine(double value, double element)) {
+    var len = this.length;
+    if (len == 0) throw IterableElementError.noElement();
+    var value = this[0];
+    for (var i = 1; i < len; ++i) {
+      value = combine(value, this[i]);
+    }
+    return value;
+  }
+
+  T fold<T>(T initialValue, T combine(T initialValue, double element)) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      initialValue = combine(initialValue, this[i]);
+    }
+    return initialValue;
+  }
+
+  Iterable<T> map<T>(T f(double element)) =>
+      new MappedIterable<double, T>(this, f);
+
+  Iterable<T> expand<T>(Iterable<T> f(double element)) =>
+      new ExpandIterable<double, T>(this, f);
+
+  bool every(bool f(double element)) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      if (!f(this[i])) return false;
+    }
+    return true;
+  }
+
+  bool any(bool f(double element)) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      if (f(this[i])) return true;
+    }
+    return false;
+  }
+
+  double firstWhere(bool test(double element), {double orElse()}) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      var element = this[i];
+      if (test(element)) return element;
+    }
+    if (orElse != null) return orElse();
+    throw IterableElementError.noElement();
+  }
+
+  double lastWhere(bool test(double element), {double orElse()}) {
+    var len = this.length;
+    for (var i = len - 1; i >= 0; --i) {
+      var element = this[i];
+      if (test(element)) {
+        return element;
+      }
+    }
+    if (orElse != null) return orElse();
+    throw IterableElementError.noElement();
+  }
+
+  double singleWhere(bool test(double element), {double orElse()}) {
+    var result = null;
+    bool foundMatching = false;
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      var element = this[i];
+      if (test(element)) {
+        if (foundMatching) {
+          throw IterableElementError.tooMany();
+        }
+        result = element;
+        foundMatching = true;
+      }
+    }
+    if (foundMatching) return result;
+    if (orElse != null) return orElse();
+    throw IterableElementError.noElement();
+  }
+
+  double elementAt(int index) {
+    return this[index];
+  }
+
+  void add(double value) {
+    throw new UnsupportedError("Cannot add to a fixed-length list");
+  }
+
+  void addAll(Iterable<double> value) {
+    throw new UnsupportedError("Cannot add to a fixed-length list");
+  }
+
+  void insert(int index, double value) {
+    throw new UnsupportedError("Cannot insert into a fixed-length list");
+  }
+
+  void insertAll(int index, Iterable<double> values) {
+    throw new UnsupportedError("Cannot insert into a fixed-length list");
+  }
+
+  void sort([int compare(double a, double b)]) {
+    Sort.sort(this, compare ?? Comparable.compare);
+  }
+
+  int indexOf(double element, [int start = 0]) {
+    if (start >= this.length) {
+      return -1;
+    } else if (start < 0) {
+      start = 0;
+    }
+    for (int i = start; i < this.length; i++) {
+      if (this[i] == element) return i;
+    }
+    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--) {
+      if (this[i] == element) return i;
+    }
+    return -1;
+  }
+
+  double removeLast() {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  double removeAt(int index) {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  void removeWhere(bool test(double element)) {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  void retainWhere(bool test(double element)) {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  double get first {
+    if (length > 0) return this[0];
+    throw IterableElementError.noElement();
+  }
+
+  double get last {
+    if (length > 0) return this[length - 1];
+    throw IterableElementError.noElement();
+  }
+
+  double get single {
+    if (length == 1) return this[0];
+    if (length == 0) throw IterableElementError.noElement();
+    throw IterableElementError.tooMany();
+  }
+
+  void setAll(int index, Iterable<double> iterable) {
+    final end = iterable.length + index;
+    setRange(index, end, iterable);
+  }
+
+  void fillRange(int start, int end, [double fillValue]) {
+    RangeError.checkValidRange(start, end, this.length);
+    for (var i = start; i < end; ++i) {
+      this[i] = fillValue;
+    }
+  }
+}
+
+mixin _TypedDoubleListMixin<SpawnedType extends List<double>>
+    on _DoubleListMixin implements List<double> {
+  SpawnedType _createList(int length);
+
+  void setRange(int start, int end, Iterable<double> from,
+      [int skipCount = 0]) {
+    // Check ranges.
+    if (0 > start || start > end || end > length) {
+      RangeError.checkValidRange(start, end, length); // Always throws.
+      assert(false);
+    }
+    if (skipCount < 0) {
+      throw RangeError.range(skipCount, 0, null, "skipCount");
+    }
+
+    final count = end - start;
+    if ((from.length - skipCount) < count) {
+      throw IterableElementError.tooFew();
+    }
+
+    if (count == 0) return;
+
+    if (from is _TypedListBase) {
+      // Note: _TypedListBase is not related to Iterable<double> so there is
+      // no promotion here.
+      final fromAsTypedList = from as _TypedListBase;
+      if (this.elementSizeInBytes == fromAsTypedList.elementSizeInBytes) {
+        if ((count < 10) && (fromAsTypedList.buffer != this.buffer)) {
+          Lists.copy(from as List<double>, skipCount, this, start, count);
+          return;
+        } else if (this.buffer._data._setRange(
+            start * elementSizeInBytes + this.offsetInBytes,
+            count * elementSizeInBytes,
+            fromAsTypedList.buffer._data,
+            skipCount * elementSizeInBytes + fromAsTypedList.offsetInBytes,
+            ClassID.getID(this),
+            ClassID.getID(from))) {
+          return;
+        }
+      } else if (fromAsTypedList.buffer == this.buffer) {
+        // Different element sizes, but same buffer means that we need
+        // an intermediate structure.
+        // TODO(srdjan): Optimize to skip copying if the range does not overlap.
+        final fromAsList = from as List<double>;
+        final tempBuffer = _createList(count);
+        for (var i = 0; i < count; i++) {
+          tempBuffer[i] = fromAsList[skipCount + i];
+        }
+        for (var i = start; i < end; i++) {
+          this[i] = tempBuffer[i - start];
+        }
+        return;
+      }
+    }
+
+    List otherList;
+    int otherStart;
+    if (from is List<double>) {
+      otherList = from;
+      otherStart = skipCount;
+    } else {
+      otherList = from.skip(skipCount).toList(growable: false);
+      otherStart = 0;
+    }
+    if (otherStart + count > otherList.length) {
+      throw IterableElementError.tooFew();
+    }
+    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 result = _createList(length);
+    result.setRange(0, length, this, start);
+    return result;
+  }
+}
+
+abstract class _Float32x4ListMixin implements List<Float32x4> {
+  int get elementSizeInBytes;
+  int get offsetInBytes;
+  _ByteBuffer get buffer;
+
+  Float32x4List _createList(int length);
+
+  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+
+  Iterable<Float32x4> followedBy(Iterable<Float32x4> other) =>
+      new FollowedByIterable<Float32x4>.firstEfficient(this, other);
+
+  List<R> cast<R>() => List.castFrom<Float32x4, R>(this);
+  void set first(Float32x4 value) {
+    if (this.length == 0) throw new RangeError.index(0, this);
+    this[0] = value;
+  }
+
+  void set last(Float32x4 value) {
+    if (this.length == 0) throw new RangeError.index(0, this);
+    this[this.length - 1] = value;
+  }
+
+  int indexWhere(bool test(Float32x4 element), [int start = 0]) {
+    if (start < 0) start = 0;
+    for (int i = start; i < length; i++) {
+      if (test(this[i])) return i;
+    }
+    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--) {
+      if (test(this[i])) return i;
+    }
+    return -1;
+  }
+
+  List<Float32x4> operator +(List<Float32x4> other) {
+    int totalLength = this.length + other.length;
+    return <Float32x4>[]
+      ..length = totalLength
+      ..setRange(0, this.length, this)
+      ..setRange(this.length, totalLength, other);
+  }
+
+  bool contains(Object element) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      if (this[i] == element) return true;
+    }
+    return false;
+  }
+
+  void shuffle([Random random]) {
+    random ??= new Random();
+    var i = this.length;
+    while (i > 1) {
+      int pos = random.nextInt(i);
+      i -= 1;
+      var tmp = this[i];
+      this[i] = this[pos];
+      this[pos] = tmp;
+    }
+  }
+
+  void setRange(int start, int end, Iterable<Float32x4> from,
+      [int skipCount = 0]) {
+    // Check ranges.
+    if (0 > start || start > end || end > length) {
+      RangeError.checkValidRange(start, end, length); // Always throws.
+      assert(false);
+    }
+    if (skipCount < 0) {
+      throw RangeError.range(skipCount, 0, null, "skipCount");
+    }
+
+    final count = end - start;
+    if ((from.length - skipCount) < count) {
+      throw IterableElementError.tooFew();
+    }
+
+    if (count == 0) return;
+
+    if (from is _TypedListBase) {
+      // Note: _TypedListBase is not related to Iterable<Float32x4> so there is
+      // no promotion here.
+      final fromAsTypedList = from as _TypedListBase;
+      if (this.elementSizeInBytes == fromAsTypedList.elementSizeInBytes) {
+        if ((count < 10) && (fromAsTypedList.buffer != this.buffer)) {
+          Lists.copy(from as List<Float32x4>, skipCount, this, start, count);
+          return;
+        } else if (this.buffer._data._setRange(
+            start * elementSizeInBytes + this.offsetInBytes,
+            count * elementSizeInBytes,
+            fromAsTypedList.buffer._data,
+            skipCount * elementSizeInBytes + fromAsTypedList.offsetInBytes,
+            ClassID.getID(this),
+            ClassID.getID(from))) {
+          return;
+        }
+      } else if (fromAsTypedList.buffer == this.buffer) {
+        // Different element sizes, but same buffer means that we need
+        // an intermediate structure.
+        // TODO(srdjan): Optimize to skip copying if the range does not overlap.
+        final fromAsList = from as List<Float32x4>;
+        final tempBuffer = _createList(count);
+        for (var i = 0; i < count; i++) {
+          tempBuffer[i] = fromAsList[skipCount + i];
+        }
+        for (var i = start; i < end; i++) {
+          this[i] = tempBuffer[i - start];
+        }
+        return;
+      }
+    }
+
+    List otherList;
+    int otherStart;
+    if (from is List<Float32x4>) {
+      otherList = from;
+      otherStart = skipCount;
+    } else {
+      otherList = from.skip(skipCount).toList(growable: false);
+      otherStart = 0;
+    }
+    if (otherStart + count > otherList.length) {
+      throw IterableElementError.tooFew();
+    }
+    Lists.copy(otherList, otherStart, this, start, count);
+  }
+
+  Iterable<Float32x4> where(bool f(Float32x4 element)) =>
+      new WhereIterable<Float32x4>(this, f);
+
+  Iterable<Float32x4> take(int n) => new SubListIterable<Float32x4>(this, 0, n);
+
+  Iterable<Float32x4> takeWhile(bool test(Float32x4 element)) =>
+      new TakeWhileIterable<Float32x4>(this, test);
+
+  Iterable<Float32x4> skip(int n) =>
+      new SubListIterable<Float32x4>(this, n, null);
+
+  Iterable<Float32x4> skipWhile(bool test(Float32x4 element)) =>
+      new SkipWhileIterable<Float32x4>(this, test);
+
+  Iterable<Float32x4> get reversed => new ReversedListIterable<Float32x4>(this);
+
+  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);
+  }
+
+  Iterator<Float32x4> get iterator => new _TypedListIterator<Float32x4>(this);
+
+  List<Float32x4> toList({bool growable: true}) {
+    return new List<Float32x4>.from(this, growable: growable);
+  }
+
+  Set<Float32x4> toSet() {
+    return new Set<Float32x4>.from(this);
+  }
+
+  void forEach(void f(Float32x4 element)) {
+    var len = this.length;
+    for (var i = 0; i < len; i++) {
+      f(this[i]);
+    }
+  }
+
+  Float32x4 reduce(Float32x4 combine(Float32x4 value, Float32x4 element)) {
+    var len = this.length;
+    if (len == 0) throw IterableElementError.noElement();
+    var value = this[0];
+    for (var i = 1; i < len; ++i) {
+      value = combine(value, this[i]);
+    }
+    return value;
+  }
+
+  T fold<T>(T initialValue, T combine(T initialValue, Float32x4 element)) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      initialValue = combine(initialValue, this[i]);
+    }
+    return initialValue;
+  }
+
+  Iterable<T> map<T>(T f(Float32x4 element)) =>
+      new MappedIterable<Float32x4, T>(this, f);
+
+  Iterable<T> expand<T>(Iterable<T> f(Float32x4 element)) =>
+      new ExpandIterable<Float32x4, T>(this, f);
+
+  bool every(bool f(Float32x4 element)) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      if (!f(this[i])) return false;
+    }
+    return true;
+  }
+
+  bool any(bool f(Float32x4 element)) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      if (f(this[i])) return true;
+    }
+    return false;
+  }
+
+  Float32x4 firstWhere(bool test(Float32x4 element), {Float32x4 orElse()}) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      var element = this[i];
+      if (test(element)) return element;
+    }
+    if (orElse != null) return orElse();
+    throw IterableElementError.noElement();
+  }
+
+  Float32x4 lastWhere(bool test(Float32x4 element), {Float32x4 orElse()}) {
+    var len = this.length;
+    for (var i = len - 1; i >= 0; --i) {
+      var element = this[i];
+      if (test(element)) {
+        return element;
+      }
+    }
+    if (orElse != null) return orElse();
+    throw IterableElementError.noElement();
+  }
+
+  Float32x4 singleWhere(bool test(Float32x4 element), {Float32x4 orElse()}) {
+    var result = null;
+    bool foundMatching = false;
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      var element = this[i];
+      if (test(element)) {
+        if (foundMatching) {
+          throw IterableElementError.tooMany();
+        }
+        result = element;
+        foundMatching = true;
+      }
+    }
+    if (foundMatching) return result;
+    if (orElse != null) return orElse();
+    throw IterableElementError.noElement();
+  }
+
+  Float32x4 elementAt(int index) {
+    return this[index];
+  }
+
+  void add(Float32x4 value) {
+    throw new UnsupportedError("Cannot add to a fixed-length list");
+  }
+
+  void addAll(Iterable<Float32x4> value) {
+    throw new UnsupportedError("Cannot add to a fixed-length list");
+  }
+
+  void insert(int index, Float32x4 value) {
+    throw new UnsupportedError("Cannot insert into a fixed-length list");
+  }
+
+  void insertAll(int index, Iterable<Float32x4> values) {
+    throw new UnsupportedError("Cannot insert into a fixed-length list");
+  }
+
+  void sort([int compare(Float32x4 a, Float32x4 b)]) {
+    if (compare == null) {
+      throw "SIMD don't have default compare.";
+    }
+    Sort.sort(this, compare);
+  }
+
+  int indexOf(Float32x4 element, [int start = 0]) {
+    if (start >= this.length) {
+      return -1;
+    } else if (start < 0) {
+      start = 0;
+    }
+    for (int i = start; i < this.length; i++) {
+      if (this[i] == element) return i;
+    }
+    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--) {
+      if (this[i] == element) return i;
+    }
+    return -1;
+  }
+
+  Float32x4 removeLast() {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  Float32x4 removeAt(int index) {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  void removeWhere(bool test(Float32x4 element)) {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  void retainWhere(bool test(Float32x4 element)) {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  Float32x4 get first {
+    if (length > 0) return this[0];
+    throw IterableElementError.noElement();
+  }
+
+  Float32x4 get last {
+    if (length > 0) return this[length - 1];
+    throw IterableElementError.noElement();
+  }
+
+  Float32x4 get single {
+    if (length == 1) return this[0];
+    if (length == 0) throw IterableElementError.noElement();
+    throw IterableElementError.tooMany();
+  }
+
+  Float32x4List sublist(int start, [int end]) {
+    end = RangeError.checkValidRange(start, end, this.length);
+    var length = end - start;
+    Float32x4List result = _createList(length);
+    result.setRange(0, length, this, start);
+    return result;
+  }
+
+  void setAll(int index, Iterable<Float32x4> iterable) {
+    final end = iterable.length + index;
+    setRange(index, end, iterable);
+  }
+
+  void fillRange(int start, int end, [Float32x4 fillValue]) {
+    RangeError.checkValidRange(start, end, this.length);
+    for (var i = start; i < end; ++i) {
+      this[i] = fillValue;
+    }
+  }
+}
+
+abstract class _Int32x4ListMixin implements List<Int32x4> {
+  int get elementSizeInBytes;
+  int get offsetInBytes;
+  _ByteBuffer get buffer;
+
+  Int32x4List _createList(int length);
+
+  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+
+  Iterable<Int32x4> followedBy(Iterable<Int32x4> other) =>
+      new FollowedByIterable<Int32x4>.firstEfficient(this, other);
+
+  List<R> cast<R>() => List.castFrom<Int32x4, R>(this);
+  void set first(Int32x4 value) {
+    if (this.length == 0) throw new RangeError.index(0, this);
+    this[0] = value;
+  }
+
+  void set last(Int32x4 value) {
+    if (this.length == 0) throw new RangeError.index(0, this);
+    this[this.length - 1] = value;
+  }
+
+  int indexWhere(bool test(Int32x4 element), [int start = 0]) {
+    if (start < 0) start = 0;
+    for (int i = start; i < length; i++) {
+      if (test(this[i])) return i;
+    }
+    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--) {
+      if (test(this[i])) return i;
+    }
+    return -1;
+  }
+
+  List<Int32x4> operator +(List<Int32x4> other) {
+    int totalLength = this.length + other.length;
+    return <Int32x4>[]
+      ..length = totalLength
+      ..setRange(0, this.length, this)
+      ..setRange(this.length, totalLength, other);
+  }
+
+  bool contains(Object element) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      if (this[i] == element) return true;
+    }
+    return false;
+  }
+
+  void shuffle([Random random]) {
+    random ??= new Random();
+    var i = this.length;
+    while (i > 1) {
+      int pos = random.nextInt(i);
+      i -= 1;
+      var tmp = this[i];
+      this[i] = this[pos];
+      this[pos] = tmp;
+    }
+  }
+
+  void setRange(int start, int end, Iterable<Int32x4> from,
+      [int skipCount = 0]) {
+    // Check ranges.
+    if (0 > start || start > end || end > length) {
+      RangeError.checkValidRange(start, end, length); // Always throws.
+      assert(false);
+    }
+    if (skipCount < 0) {
+      throw RangeError.range(skipCount, 0, null, "skipCount");
+    }
+
+    final count = end - start;
+    if ((from.length - skipCount) < count) {
+      throw IterableElementError.tooFew();
+    }
+
+    if (count == 0) return;
+
+    if (from is _TypedListBase) {
+      // Note: _TypedListBase is not related to Iterable<Int32x4> so there is
+      // no promotion here.
+      final fromAsTypedList = from as _TypedListBase;
+      if (this.elementSizeInBytes == fromAsTypedList.elementSizeInBytes) {
+        if ((count < 10) && (fromAsTypedList.buffer != this.buffer)) {
+          Lists.copy(from as List<Int32x4>, skipCount, this, start, count);
+          return;
+        } else if (this.buffer._data._setRange(
+            start * elementSizeInBytes + this.offsetInBytes,
+            count * elementSizeInBytes,
+            fromAsTypedList.buffer._data,
+            skipCount * elementSizeInBytes + fromAsTypedList.offsetInBytes,
+            ClassID.getID(this),
+            ClassID.getID(from))) {
+          return;
+        }
+      } else if (fromAsTypedList.buffer == this.buffer) {
+        // Different element sizes, but same buffer means that we need
+        // an intermediate structure.
+        // TODO(srdjan): Optimize to skip copying if the range does not overlap.
+        final fromAsList = from as List<Int32x4>;
+        final tempBuffer = _createList(count);
+        for (var i = 0; i < count; i++) {
+          tempBuffer[i] = fromAsList[skipCount + i];
+        }
+        for (var i = start; i < end; i++) {
+          this[i] = tempBuffer[i - start];
+        }
+        return;
+      }
+    }
+
+    List otherList;
+    int otherStart;
+    if (from is List<Int32x4>) {
+      otherList = from;
+      otherStart = skipCount;
+    } else {
+      otherList = from.skip(skipCount).toList(growable: false);
+      otherStart = 0;
+    }
+    if (otherStart + count > otherList.length) {
+      throw IterableElementError.tooFew();
+    }
+    Lists.copy(otherList, otherStart, this, start, count);
+  }
+
+  Iterable<Int32x4> where(bool f(Int32x4 element)) =>
+      new WhereIterable<Int32x4>(this, f);
+
+  Iterable<Int32x4> take(int n) => new SubListIterable<Int32x4>(this, 0, n);
+
+  Iterable<Int32x4> takeWhile(bool test(Int32x4 element)) =>
+      new TakeWhileIterable<Int32x4>(this, test);
+
+  Iterable<Int32x4> skip(int n) => new SubListIterable<Int32x4>(this, n, null);
+
+  Iterable<Int32x4> skipWhile(bool test(Int32x4 element)) =>
+      new SkipWhileIterable<Int32x4>(this, test);
+
+  Iterable<Int32x4> get reversed => new ReversedListIterable<Int32x4>(this);
+
+  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);
+  }
+
+  Iterator<Int32x4> get iterator => new _TypedListIterator<Int32x4>(this);
+
+  List<Int32x4> toList({bool growable: true}) {
+    return new List<Int32x4>.from(this, growable: growable);
+  }
+
+  Set<Int32x4> toSet() {
+    return new Set<Int32x4>.from(this);
+  }
+
+  void forEach(void f(Int32x4 element)) {
+    var len = this.length;
+    for (var i = 0; i < len; i++) {
+      f(this[i]);
+    }
+  }
+
+  Int32x4 reduce(Int32x4 combine(Int32x4 value, Int32x4 element)) {
+    var len = this.length;
+    if (len == 0) throw IterableElementError.noElement();
+    var value = this[0];
+    for (var i = 1; i < len; ++i) {
+      value = combine(value, this[i]);
+    }
+    return value;
+  }
+
+  T fold<T>(T initialValue, T combine(T initialValue, Int32x4 element)) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      initialValue = combine(initialValue, this[i]);
+    }
+    return initialValue;
+  }
+
+  Iterable<T> map<T>(T f(Int32x4 element)) =>
+      new MappedIterable<Int32x4, T>(this, f);
+
+  Iterable<T> expand<T>(Iterable<T> f(Int32x4 element)) =>
+      new ExpandIterable<Int32x4, T>(this, f);
+
+  bool every(bool f(Int32x4 element)) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      if (!f(this[i])) return false;
+    }
+    return true;
+  }
+
+  bool any(bool f(Int32x4 element)) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      if (f(this[i])) return true;
+    }
+    return false;
+  }
+
+  Int32x4 firstWhere(bool test(Int32x4 element), {Int32x4 orElse()}) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      var element = this[i];
+      if (test(element)) return element;
+    }
+    if (orElse != null) return orElse();
+    throw IterableElementError.noElement();
+  }
+
+  Int32x4 lastWhere(bool test(Int32x4 element), {Int32x4 orElse()}) {
+    var len = this.length;
+    for (var i = len - 1; i >= 0; --i) {
+      var element = this[i];
+      if (test(element)) {
+        return element;
+      }
+    }
+    if (orElse != null) return orElse();
+    throw IterableElementError.noElement();
+  }
+
+  Int32x4 singleWhere(bool test(Int32x4 element), {Int32x4 orElse()}) {
+    var result = null;
+    bool foundMatching = false;
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      var element = this[i];
+      if (test(element)) {
+        if (foundMatching) {
+          throw IterableElementError.tooMany();
+        }
+        result = element;
+        foundMatching = true;
+      }
+    }
+    if (foundMatching) return result;
+    if (orElse != null) return orElse();
+    throw IterableElementError.noElement();
+  }
+
+  Int32x4 elementAt(int index) {
+    return this[index];
+  }
+
+  void add(Int32x4 value) {
+    throw new UnsupportedError("Cannot add to a fixed-length list");
+  }
+
+  void addAll(Iterable<Int32x4> value) {
+    throw new UnsupportedError("Cannot add to a fixed-length list");
+  }
+
+  void insert(int index, Int32x4 value) {
+    throw new UnsupportedError("Cannot insert into a fixed-length list");
+  }
+
+  void insertAll(int index, Iterable<Int32x4> values) {
+    throw new UnsupportedError("Cannot insert into a fixed-length list");
+  }
+
+  void sort([int compare(Int32x4 a, Int32x4 b)]) {
+    if (compare == null) {
+      throw "SIMD don't have default compare.";
+    }
+    Sort.sort(this, compare);
+  }
+
+  int indexOf(Int32x4 element, [int start = 0]) {
+    if (start >= this.length) {
+      return -1;
+    } else if (start < 0) {
+      start = 0;
+    }
+    for (int i = start; i < this.length; i++) {
+      if (this[i] == element) return i;
+    }
+    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--) {
+      if (this[i] == element) return i;
+    }
+    return -1;
+  }
+
+  Int32x4 removeLast() {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  Int32x4 removeAt(int index) {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  void removeWhere(bool test(Int32x4 element)) {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  void retainWhere(bool test(Int32x4 element)) {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  Int32x4 get first {
+    if (length > 0) return this[0];
+    throw IterableElementError.noElement();
+  }
+
+  Int32x4 get last {
+    if (length > 0) return this[length - 1];
+    throw IterableElementError.noElement();
+  }
+
+  Int32x4 get single {
+    if (length == 1) return this[0];
+    if (length == 0) throw IterableElementError.noElement();
+    throw IterableElementError.tooMany();
+  }
+
+  Int32x4List sublist(int start, [int end]) {
+    end = RangeError.checkValidRange(start, end, this.length);
+    var length = end - start;
+    Int32x4List result = _createList(length);
+    result.setRange(0, length, this, start);
+    return result;
+  }
+
+  void setAll(int index, Iterable<Int32x4> iterable) {
+    final end = iterable.length + index;
+    setRange(index, end, iterable);
+  }
+
+  void fillRange(int start, int end, [Int32x4 fillValue]) {
+    RangeError.checkValidRange(start, end, this.length);
+    for (var i = start; i < end; ++i) {
+      this[i] = fillValue;
+    }
+  }
+}
+
+abstract class _Float64x2ListMixin implements List<Float64x2> {
+  int get elementSizeInBytes;
+  int get offsetInBytes;
+  _ByteBuffer get buffer;
+
+  Float64x2List _createList(int length);
+
+  Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+
+  Iterable<Float64x2> followedBy(Iterable<Float64x2> other) =>
+      new FollowedByIterable<Float64x2>.firstEfficient(this, other);
+
+  List<R> cast<R>() => List.castFrom<Float64x2, R>(this);
+  void set first(Float64x2 value) {
+    if (this.length == 0) throw new RangeError.index(0, this);
+    this[0] = value;
+  }
+
+  void set last(Float64x2 value) {
+    if (this.length == 0) throw new RangeError.index(0, this);
+    this[this.length - 1] = value;
+  }
+
+  int indexWhere(bool test(Float64x2 element), [int start = 0]) {
+    if (start < 0) start = 0;
+    for (int i = start; i < length; i++) {
+      if (test(this[i])) return i;
+    }
+    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--) {
+      if (test(this[i])) return i;
+    }
+    return -1;
+  }
+
+  List<Float64x2> operator +(List<Float64x2> other) {
+    int totalLength = this.length + other.length;
+    return <Float64x2>[]
+      ..length = totalLength
+      ..setRange(0, this.length, this)
+      ..setRange(this.length, totalLength, other);
+  }
+
+  bool contains(Object element) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      if (this[i] == element) return true;
+    }
+    return false;
+  }
+
+  void shuffle([Random random]) {
+    random ??= new Random();
+    var i = this.length;
+    while (i > 1) {
+      int pos = random.nextInt(i);
+      i -= 1;
+      var tmp = this[i];
+      this[i] = this[pos];
+      this[pos] = tmp;
+    }
+  }
+
+  void setRange(int start, int end, Iterable<Float64x2> from,
+      [int skipCount = 0]) {
+    // Check ranges.
+    if (0 > start || start > end || end > length) {
+      RangeError.checkValidRange(start, end, length); // Always throws.
+      assert(false);
+    }
+    if (skipCount < 0) {
+      throw RangeError.range(skipCount, 0, null, "skipCount");
+    }
+
+    final count = end - start;
+    if ((from.length - skipCount) < count) {
+      throw IterableElementError.tooFew();
+    }
+
+    if (count == 0) return;
+
+    if (from is _TypedListBase) {
+      // Note: _TypedListBase is not related to Iterable<Float64x2> so there is
+      // no promotion here.
+      final fromAsTypedList = from as _TypedListBase;
+      if (this.elementSizeInBytes == fromAsTypedList.elementSizeInBytes) {
+        if ((count < 10) && (fromAsTypedList.buffer != this.buffer)) {
+          Lists.copy(from as List<Float64x2>, skipCount, this, start, count);
+          return;
+        } else if (this.buffer._data._setRange(
+            start * elementSizeInBytes + this.offsetInBytes,
+            count * elementSizeInBytes,
+            fromAsTypedList.buffer._data,
+            skipCount * elementSizeInBytes + fromAsTypedList.offsetInBytes,
+            ClassID.getID(this),
+            ClassID.getID(from))) {
+          return;
+        }
+      } else if (fromAsTypedList.buffer == this.buffer) {
+        // Different element sizes, but same buffer means that we need
+        // an intermediate structure.
+        // TODO(srdjan): Optimize to skip copying if the range does not overlap.
+        final fromAsList = from as List<Float64x2>;
+        final tempBuffer = _createList(count);
+        for (var i = 0; i < count; i++) {
+          tempBuffer[i] = fromAsList[skipCount + i];
+        }
+        for (var i = start; i < end; i++) {
+          this[i] = tempBuffer[i - start];
+        }
+        return;
+      }
+    }
+
+    List otherList;
+    int otherStart;
+    if (from is List<Float64x2>) {
+      otherList = from;
+      otherStart = skipCount;
+    } else {
+      otherList = from.skip(skipCount).toList(growable: false);
+      otherStart = 0;
+    }
+    if (otherStart + count > otherList.length) {
+      throw IterableElementError.tooFew();
+    }
+    Lists.copy(otherList, otherStart, this, start, count);
+  }
+
+  Iterable<Float64x2> where(bool f(Float64x2 element)) =>
+      new WhereIterable<Float64x2>(this, f);
+
+  Iterable<Float64x2> take(int n) => new SubListIterable<Float64x2>(this, 0, n);
+
+  Iterable<Float64x2> takeWhile(bool test(Float64x2 element)) =>
+      new TakeWhileIterable<Float64x2>(this, test);
+
+  Iterable<Float64x2> skip(int n) =>
+      new SubListIterable<Float64x2>(this, n, null);
+
+  Iterable<Float64x2> skipWhile(bool test(Float64x2 element)) =>
+      new SkipWhileIterable<Float64x2>(this, test);
+
+  Iterable<Float64x2> get reversed => new ReversedListIterable<Float64x2>(this);
+
+  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);
+  }
+
+  Iterator<Float64x2> get iterator => new _TypedListIterator<Float64x2>(this);
+
+  List<Float64x2> toList({bool growable: true}) {
+    return new List<Float64x2>.from(this, growable: growable);
+  }
+
+  Set<Float64x2> toSet() {
+    return new Set<Float64x2>.from(this);
+  }
+
+  void forEach(void f(Float64x2 element)) {
+    var len = this.length;
+    for (var i = 0; i < len; i++) {
+      f(this[i]);
+    }
+  }
+
+  Float64x2 reduce(Float64x2 combine(Float64x2 value, Float64x2 element)) {
+    var len = this.length;
+    if (len == 0) throw IterableElementError.noElement();
+    var value = this[0];
+    for (var i = 1; i < len; ++i) {
+      value = combine(value, this[i]);
+    }
+    return value;
+  }
+
+  T fold<T>(T initialValue, T combine(T initialValue, Float64x2 element)) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      initialValue = combine(initialValue, this[i]);
+    }
+    return initialValue;
+  }
+
+  Iterable<T> map<T>(T f(Float64x2 element)) =>
+      new MappedIterable<Float64x2, T>(this, f);
+
+  Iterable<T> expand<T>(Iterable<T> f(Float64x2 element)) =>
+      new ExpandIterable<Float64x2, T>(this, f);
+
+  bool every(bool f(Float64x2 element)) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      if (!f(this[i])) return false;
+    }
+    return true;
+  }
+
+  bool any(bool f(Float64x2 element)) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      if (f(this[i])) return true;
+    }
+    return false;
+  }
+
+  Float64x2 firstWhere(bool test(Float64x2 element), {Float64x2 orElse()}) {
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      var element = this[i];
+      if (test(element)) return element;
+    }
+    if (orElse != null) return orElse();
+    throw IterableElementError.noElement();
+  }
+
+  Float64x2 lastWhere(bool test(Float64x2 element), {Float64x2 orElse()}) {
+    var len = this.length;
+    for (var i = len - 1; i >= 0; --i) {
+      var element = this[i];
+      if (test(element)) {
+        return element;
+      }
+    }
+    if (orElse != null) return orElse();
+    throw IterableElementError.noElement();
+  }
+
+  Float64x2 singleWhere(bool test(Float64x2 element), {Float64x2 orElse()}) {
+    var result = null;
+    bool foundMatching = false;
+    var len = this.length;
+    for (var i = 0; i < len; ++i) {
+      var element = this[i];
+      if (test(element)) {
+        if (foundMatching) {
+          throw IterableElementError.tooMany();
+        }
+        result = element;
+        foundMatching = true;
+      }
+    }
+    if (foundMatching) return result;
+    if (orElse != null) return orElse();
+    throw IterableElementError.noElement();
+  }
+
+  Float64x2 elementAt(int index) {
+    return this[index];
+  }
+
+  void add(Float64x2 value) {
+    throw new UnsupportedError("Cannot add to a fixed-length list");
+  }
+
+  void addAll(Iterable<Float64x2> value) {
+    throw new UnsupportedError("Cannot add to a fixed-length list");
+  }
+
+  void insert(int index, Float64x2 value) {
+    throw new UnsupportedError("Cannot insert into a fixed-length list");
+  }
+
+  void insertAll(int index, Iterable<Float64x2> values) {
+    throw new UnsupportedError("Cannot insert into a fixed-length list");
+  }
+
+  void sort([int compare(Float64x2 a, Float64x2 b)]) {
+    if (compare == null) {
+      throw "SIMD don't have default compare.";
+    }
+    Sort.sort(this, compare);
+  }
+
+  int indexOf(Float64x2 element, [int start = 0]) {
+    if (start >= this.length) {
+      return -1;
+    } else if (start < 0) {
+      start = 0;
+    }
+    for (int i = start; i < this.length; i++) {
+      if (this[i] == element) return i;
+    }
+    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--) {
+      if (this[i] == element) return i;
+    }
+    return -1;
+  }
+
+  Float64x2 removeLast() {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  Float64x2 removeAt(int index) {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  void removeWhere(bool test(Float64x2 element)) {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  void retainWhere(bool test(Float64x2 element)) {
+    throw new UnsupportedError("Cannot remove from a fixed-length list");
+  }
+
+  Float64x2 get first {
+    if (length > 0) return this[0];
+    throw IterableElementError.noElement();
+  }
+
+  Float64x2 get last {
+    if (length > 0) return this[length - 1];
+    throw IterableElementError.noElement();
+  }
+
+  Float64x2 get single {
+    if (length == 1) return this[0];
+    if (length == 0) throw IterableElementError.noElement();
+    throw IterableElementError.tooMany();
+  }
+
+  Float64x2List sublist(int start, [int end]) {
+    end = RangeError.checkValidRange(start, end, this.length);
+    var length = end - start;
+    Float64x2List result = _createList(length);
+    result.setRange(0, length, this, start);
+    return result;
+  }
+
+  void setAll(int index, Iterable<Float64x2> iterable) {
+    final end = iterable.length + index;
+    setRange(index, end, iterable);
+  }
+
+  void fillRange(int start, int end, [Float64x2 fillValue]) {
+    RangeError.checkValidRange(start, end, this.length);
+    for (var i = start; i < end; ++i) {
+      this[i] = fillValue;
+    }
+  }
+}
+
+@pragma("vm:entry-point")
+class _ByteBuffer implements ByteBuffer {
+  final _TypedList _data;
+
+  _ByteBuffer(this._data);
+
+  @pragma("vm:entry-point")
+  factory _ByteBuffer._New(data) => new _ByteBuffer(data);
+
+  // Forward calls to _data.
+  int get lengthInBytes => _data.lengthInBytes;
+  int get hashCode => _data.hashCode;
+  bool operator ==(Object other) =>
+      (other is _ByteBuffer) && identical(_data, other._data);
+
+  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]) {
+    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]) {
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Uint8List.bytesPerElement;
+    _rangeCheck(
+        this.lengthInBytes, offsetInBytes, length * Uint8List.bytesPerElement);
+    return new _Uint8ArrayView._(this._data, offsetInBytes, length);
+  }
+
+  Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int length]) {
+    length ??= (this.lengthInBytes - offsetInBytes) ~/
+        Uint8ClampedList.bytesPerElement;
+    _rangeCheck(this.lengthInBytes, offsetInBytes,
+        length * Uint8ClampedList.bytesPerElement);
+    return new _Uint8ClampedArrayView._(this._data, offsetInBytes, length);
+  }
+
+  Int16List asInt16List([int offsetInBytes = 0, int length]) {
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Int16List.bytesPerElement;
+    _rangeCheck(
+        this.lengthInBytes, offsetInBytes, length * Int16List.bytesPerElement);
+    _offsetAlignmentCheck(offsetInBytes, Int16List.bytesPerElement);
+    return new _Int16ArrayView._(this._data, offsetInBytes, length);
+  }
+
+  Uint16List asUint16List([int offsetInBytes = 0, int length]) {
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Uint16List.bytesPerElement;
+    _rangeCheck(
+        this.lengthInBytes, offsetInBytes, length * Uint16List.bytesPerElement);
+    _offsetAlignmentCheck(offsetInBytes, Uint16List.bytesPerElement);
+    return new _Uint16ArrayView._(this._data, offsetInBytes, length);
+  }
+
+  Int32List asInt32List([int offsetInBytes = 0, int length]) {
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Int32List.bytesPerElement;
+    _rangeCheck(
+        this.lengthInBytes, offsetInBytes, length * Int32List.bytesPerElement);
+    _offsetAlignmentCheck(offsetInBytes, Int32List.bytesPerElement);
+    return new _Int32ArrayView._(this._data, offsetInBytes, length);
+  }
+
+  Uint32List asUint32List([int offsetInBytes = 0, int length]) {
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Uint32List.bytesPerElement;
+    _rangeCheck(
+        this.lengthInBytes, offsetInBytes, length * Uint32List.bytesPerElement);
+    _offsetAlignmentCheck(offsetInBytes, Uint32List.bytesPerElement);
+    return new _Uint32ArrayView._(this._data, offsetInBytes, length);
+  }
+
+  Int64List asInt64List([int offsetInBytes = 0, int length]) {
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Int64List.bytesPerElement;
+    _rangeCheck(
+        this.lengthInBytes, offsetInBytes, length * Int64List.bytesPerElement);
+    _offsetAlignmentCheck(offsetInBytes, Int64List.bytesPerElement);
+    return new _Int64ArrayView._(this._data, offsetInBytes, length);
+  }
+
+  Uint64List asUint64List([int offsetInBytes = 0, int length]) {
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Uint64List.bytesPerElement;
+    _rangeCheck(
+        this.lengthInBytes, offsetInBytes, length * Uint64List.bytesPerElement);
+    _offsetAlignmentCheck(offsetInBytes, Uint64List.bytesPerElement);
+    return new _Uint64ArrayView._(this._data, offsetInBytes, length);
+  }
+
+  Float32List asFloat32List([int offsetInBytes = 0, int length]) {
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Float32List.bytesPerElement;
+    _rangeCheck(this.lengthInBytes, offsetInBytes,
+        length * Float32List.bytesPerElement);
+    _offsetAlignmentCheck(offsetInBytes, Float32List.bytesPerElement);
+    return new _Float32ArrayView._(this._data, offsetInBytes, length);
+  }
+
+  Float64List asFloat64List([int offsetInBytes = 0, int length]) {
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Float64List.bytesPerElement;
+    _rangeCheck(this.lengthInBytes, offsetInBytes,
+        length * Float64List.bytesPerElement);
+    _offsetAlignmentCheck(offsetInBytes, Float64List.bytesPerElement);
+    return new _Float64ArrayView._(this._data, offsetInBytes, length);
+  }
+
+  Float32x4List asFloat32x4List([int offsetInBytes = 0, int length]) {
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Float32x4List.bytesPerElement;
+    _rangeCheck(this.lengthInBytes, offsetInBytes,
+        length * Float32x4List.bytesPerElement);
+    _offsetAlignmentCheck(offsetInBytes, Float32x4List.bytesPerElement);
+    return new _Float32x4ArrayView._(this._data, offsetInBytes, length);
+  }
+
+  Int32x4List asInt32x4List([int offsetInBytes = 0, int length]) {
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Int32x4List.bytesPerElement;
+    _rangeCheck(this.lengthInBytes, offsetInBytes,
+        length * Int32x4List.bytesPerElement);
+    _offsetAlignmentCheck(offsetInBytes, Int32x4List.bytesPerElement);
+    return new _Int32x4ArrayView._(this._data, offsetInBytes, length);
+  }
+
+  Float64x2List asFloat64x2List([int offsetInBytes = 0, int length]) {
+    length ??=
+        (this.lengthInBytes - offsetInBytes) ~/ Float64x2List.bytesPerElement;
+    _rangeCheck(this.lengthInBytes, offsetInBytes,
+        length * Float64x2List.bytesPerElement);
+    _offsetAlignmentCheck(offsetInBytes, Float64x2List.bytesPerElement);
+    return new _Float64x2ArrayView._(this._data, offsetInBytes, length);
+  }
+}
+
+abstract class _TypedList extends _TypedListBase {
+  int get elementSizeInBytes;
+
+  // Default method implementing parts of the TypedData interface.
+  int get offsetInBytes {
+    return 0;
+  }
+
+  int get lengthInBytes {
+    return length * elementSizeInBytes;
+  }
+
+  _ByteBuffer get buffer => new _ByteBuffer(this);
+
+  // Methods implementing the collection interface.
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  @pragma("vm:prefer-inline")
+  int get length native "TypedData_length";
+
+  // Internal utility methods.
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  int _getInt8(int offsetInBytes) native "TypedData_GetInt8";
+  void _setInt8(int offsetInBytes, int value) native "TypedData_SetInt8";
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  int _getUint8(int offsetInBytes) native "TypedData_GetUint8";
+  void _setUint8(int offsetInBytes, int value) native "TypedData_SetUint8";
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  int _getInt16(int offsetInBytes) native "TypedData_GetInt16";
+  void _setInt16(int offsetInBytes, int value) native "TypedData_SetInt16";
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  int _getUint16(int offsetInBytes) native "TypedData_GetUint16";
+  void _setUint16(int offsetInBytes, int value) native "TypedData_SetUint16";
+
+  int _getInt32(int offsetInBytes) native "TypedData_GetInt32";
+  void _setInt32(int offsetInBytes, int value) native "TypedData_SetInt32";
+
+  int _getUint32(int offsetInBytes) native "TypedData_GetUint32";
+  void _setUint32(int offsetInBytes, int value) native "TypedData_SetUint32";
+
+  int _getInt64(int offsetInBytes) native "TypedData_GetInt64";
+  void _setInt64(int offsetInBytes, int value) native "TypedData_SetInt64";
+
+  int _getUint64(int offsetInBytes) native "TypedData_GetUint64";
+  void _setUint64(int offsetInBytes, int value) native "TypedData_SetUint64";
+
+  @pragma("vm:exact-result-type", "dart:core#_Double")
+  double _getFloat32(int offsetInBytes) native "TypedData_GetFloat32";
+  void _setFloat32(int offsetInBytes, double value)
+      native "TypedData_SetFloat32";
+
+  @pragma("vm:exact-result-type", "dart:core#_Double")
+  double _getFloat64(int offsetInBytes) native "TypedData_GetFloat64";
+  void _setFloat64(int offsetInBytes, double value)
+      native "TypedData_SetFloat64";
+
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 _getFloat32x4(int offsetInBytes) native "TypedData_GetFloat32x4";
+  void _setFloat32x4(int offsetInBytes, Float32x4 value)
+      native "TypedData_SetFloat32x4";
+
+  @pragma("vm:exact-result-type", _Int32x4)
+  Int32x4 _getInt32x4(int offsetInBytes) native "TypedData_GetInt32x4";
+  void _setInt32x4(int offsetInBytes, Int32x4 value)
+      native "TypedData_SetInt32x4";
+
+  Float64x2 _getFloat64x2(int offsetInBytes) native "TypedData_GetFloat64x2";
+  void _setFloat64x2(int offsetInBytes, Float64x2 value)
+      native "TypedData_SetFloat64x2";
+
+  /**
+   * Stores the [CodeUnits] as UTF-16 units into this TypedData at
+   * positions [start]..[end] (uint16 indices).
+   */
+  void _setCodeUnits(
+      CodeUnits units, int byteStart, int length, int skipCount) {
+    assert(byteStart + length * Uint16List.bytesPerElement <= lengthInBytes);
+    String string = CodeUnits.stringOf(units);
+    int sliceEnd = skipCount + length;
+    RangeError.checkValidRange(
+        skipCount, sliceEnd, string.length, "skipCount", "skipCount + length");
+    for (int i = 0; i < length; i++) {
+      _setUint16(byteStart + i * Uint16List.bytesPerElement,
+          string.codeUnitAt(skipCount + i));
+    }
+  }
+}
+
+@patch
+class Int8List {
+  @patch
+  @pragma("vm:exact-result-type", _Int8List)
+  factory Int8List(int length) native "TypedData_Int8Array_new";
+
+  @patch
+  factory Int8List.fromList(List<int> elements) {
+    return new Int8List(elements.length)
+      ..setRange(0, elements.length, elements);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Int8List extends _TypedList
+    with _IntListMixin, _TypedIntListMixin<Int8List>
+    implements Int8List {
+  factory _Int8List._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing List interface.
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getInt8(index);
+  }
+
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setInt8(index, _toInt8(value));
+  }
+
+  // Method(s) implementing TypedData interface.
+  int get elementSizeInBytes {
+    return Int8List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Int8List _createList(int length) {
+    return new Int8List(length);
+  }
+}
+
+@patch
+class Uint8List {
+  @patch
+  @pragma("vm:exact-result-type", _Uint8List)
+  factory Uint8List(int length) native "TypedData_Uint8Array_new";
+
+  @patch
+  factory Uint8List.fromList(List<int> elements) {
+    return new Uint8List(elements.length)
+      ..setRange(0, elements.length, elements);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Uint8List extends _TypedList
+    with _IntListMixin, _TypedIntListMixin<Uint8List>
+    implements Uint8List {
+  factory _Uint8List._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Methods implementing List interface.
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getUint8(index);
+  }
+
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setUint8(index, _toUint8(value));
+  }
+
+  // Methods implementing TypedData interface.
+  int get elementSizeInBytes {
+    return Uint8List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Uint8List _createList(int length) {
+    return new Uint8List(length);
+  }
+}
+
+@patch
+class Uint8ClampedList {
+  @patch
+  @pragma("vm:exact-result-type", _Uint8ClampedList)
+  factory Uint8ClampedList(int length) native "TypedData_Uint8ClampedArray_new";
+
+  @patch
+  factory Uint8ClampedList.fromList(List<int> elements) {
+    return new Uint8ClampedList(elements.length)
+      ..setRange(0, elements.length, elements);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Uint8ClampedList extends _TypedList
+    with _IntListMixin, _TypedIntListMixin<Uint8ClampedList>
+    implements Uint8ClampedList {
+  factory _Uint8ClampedList._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Methods implementing List interface.
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getUint8(index);
+  }
+
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setUint8(index, _toClampedUint8(value));
+  }
+
+  // Methods implementing TypedData interface.
+  int get elementSizeInBytes {
+    return Uint8List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Uint8ClampedList _createList(int length) {
+    return new Uint8ClampedList(length);
+  }
+}
+
+@patch
+class Int16List {
+  @patch
+  @pragma("vm:exact-result-type", _Int16List)
+  factory Int16List(int length) native "TypedData_Int16Array_new";
+
+  @patch
+  factory Int16List.fromList(List<int> elements) {
+    return new Int16List(elements.length)
+      ..setRange(0, elements.length, elements);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Int16List extends _TypedList
+    with _IntListMixin, _TypedIntListMixin<Int16List>
+    implements Int16List {
+  factory _Int16List._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing List interface.
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedInt16(index);
+  }
+
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedInt16(index, _toInt16(value));
+  }
+
+  void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) {
+    if (iterable is CodeUnits) {
+      end = RangeError.checkValidRange(start, end, this.length);
+      int length = end - start;
+      int byteStart = this.offsetInBytes + start * Int16List.bytesPerElement;
+      _setCodeUnits(iterable, byteStart, length, skipCount);
+    } else {
+      super.setRange(start, end, iterable, skipCount);
+    }
+  }
+
+  // Method(s) implementing TypedData interface.
+  int get elementSizeInBytes {
+    return Int16List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Int16List _createList(int length) {
+    return new Int16List(length);
+  }
+
+  int _getIndexedInt16(int index) {
+    return _getInt16(index * Int16List.bytesPerElement);
+  }
+
+  void _setIndexedInt16(int index, int value) {
+    _setInt16(index * Int16List.bytesPerElement, value);
+  }
+}
+
+@patch
+class Uint16List {
+  @patch
+  @pragma("vm:exact-result-type", _Uint16List)
+  factory Uint16List(int length) native "TypedData_Uint16Array_new";
+
+  @patch
+  factory Uint16List.fromList(List<int> elements) {
+    return new Uint16List(elements.length)
+      ..setRange(0, elements.length, elements);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Uint16List extends _TypedList
+    with _IntListMixin, _TypedIntListMixin<Uint16List>
+    implements Uint16List {
+  factory _Uint16List._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedUint16(index);
+  }
+
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedUint16(index, _toUint16(value));
+  }
+
+  void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) {
+    if (iterable is CodeUnits) {
+      end = RangeError.checkValidRange(start, end, this.length);
+      int length = end - start;
+      int byteStart = this.offsetInBytes + start * Uint16List.bytesPerElement;
+      _setCodeUnits(iterable, byteStart, length, skipCount);
+    } else {
+      super.setRange(start, end, iterable, skipCount);
+    }
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Uint16List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Uint16List _createList(int length) {
+    return new Uint16List(length);
+  }
+
+  int _getIndexedUint16(int index) {
+    return _getUint16(index * Uint16List.bytesPerElement);
+  }
+
+  void _setIndexedUint16(int index, int value) {
+    _setUint16(index * Uint16List.bytesPerElement, value);
+  }
+}
+
+@patch
+class Int32List {
+  @patch
+  @pragma("vm:exact-result-type", _Int32List)
+  factory Int32List(int length) native "TypedData_Int32Array_new";
+
+  @patch
+  factory Int32List.fromList(List<int> elements) {
+    return new Int32List(elements.length)
+      ..setRange(0, elements.length, elements);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Int32List extends _TypedList
+    with _IntListMixin, _TypedIntListMixin<Int32List>
+    implements Int32List {
+  factory _Int32List._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedInt32(index);
+  }
+
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedInt32(index, _toInt32(value));
+  }
+
+  // Method(s) implementing TypedData interface.
+  int get elementSizeInBytes {
+    return Int32List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Int32List _createList(int length) {
+    return new Int32List(length);
+  }
+
+  int _getIndexedInt32(int index) {
+    return _getInt32(index * Int32List.bytesPerElement);
+  }
+
+  void _setIndexedInt32(int index, int value) {
+    _setInt32(index * Int32List.bytesPerElement, value);
+  }
+}
+
+@patch
+class Uint32List {
+  @patch
+  @pragma("vm:exact-result-type", _Uint32List)
+  factory Uint32List(int length) native "TypedData_Uint32Array_new";
+
+  @patch
+  factory Uint32List.fromList(List<int> elements) {
+    return new Uint32List(elements.length)
+      ..setRange(0, elements.length, elements);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Uint32List extends _TypedList
+    with _IntListMixin, _TypedIntListMixin<Uint32List>
+    implements Uint32List {
+  factory _Uint32List._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedUint32(index);
+  }
+
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedUint32(index, _toUint32(value));
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Uint32List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Uint32List _createList(int length) {
+    return new Uint32List(length);
+  }
+
+  int _getIndexedUint32(int index) {
+    return _getUint32(index * Uint32List.bytesPerElement);
+  }
+
+  void _setIndexedUint32(int index, int value) {
+    _setUint32(index * Uint32List.bytesPerElement, value);
+  }
+}
+
+@patch
+class Int64List {
+  @patch
+  @pragma("vm:exact-result-type", _Int64List)
+  factory Int64List(int length) native "TypedData_Int64Array_new";
+
+  @patch
+  factory Int64List.fromList(List<int> elements) {
+    return new Int64List(elements.length)
+      ..setRange(0, elements.length, elements);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Int64List extends _TypedList
+    with _IntListMixin, _TypedIntListMixin<Int64List>
+    implements Int64List {
+  factory _Int64List._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedInt64(index);
+  }
+
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedInt64(index, value);
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Int64List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Int64List _createList(int length) {
+    return new Int64List(length);
+  }
+
+  int _getIndexedInt64(int index) {
+    return _getInt64(index * Int64List.bytesPerElement);
+  }
+
+  void _setIndexedInt64(int index, int value) {
+    _setInt64(index * Int64List.bytesPerElement, value);
+  }
+}
+
+@patch
+class Uint64List {
+  @patch
+  @pragma("vm:exact-result-type", _Uint64List)
+  factory Uint64List(int length) native "TypedData_Uint64Array_new";
+
+  @patch
+  factory Uint64List.fromList(List<int> elements) {
+    return new Uint64List(elements.length)
+      ..setRange(0, elements.length, elements);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Uint64List extends _TypedList
+    with _IntListMixin, _TypedIntListMixin<Uint64List>
+    implements Uint64List {
+  factory _Uint64List._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedUint64(index);
+  }
+
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedUint64(index, value);
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Uint64List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Uint64List _createList(int length) {
+    return new Uint64List(length);
+  }
+
+  int _getIndexedUint64(int index) {
+    return _getUint64(index * Uint64List.bytesPerElement);
+  }
+
+  void _setIndexedUint64(int index, int value) {
+    _setUint64(index * Uint64List.bytesPerElement, value);
+  }
+}
+
+@patch
+class Float32List {
+  @patch
+  @pragma("vm:exact-result-type", _Float32List)
+  factory Float32List(int length) native "TypedData_Float32Array_new";
+
+  @patch
+  factory Float32List.fromList(List<double> elements) {
+    return new Float32List(elements.length)
+      ..setRange(0, elements.length, elements);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Float32List extends _TypedList
+    with _DoubleListMixin, _TypedDoubleListMixin<Float32List>
+    implements Float32List {
+  factory _Float32List._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  @pragma("vm:exact-result-type", "dart:core#_Double")
+  double operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedFloat32(index);
+  }
+
+  void operator []=(int index, double value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedFloat32(index, value);
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Float32List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Float32List _createList(int length) {
+    return new Float32List(length);
+  }
+
+  double _getIndexedFloat32(int index) {
+    return _getFloat32(index * Float32List.bytesPerElement);
+  }
+
+  void _setIndexedFloat32(int index, double value) {
+    _setFloat32(index * Float32List.bytesPerElement, value);
+  }
+}
+
+@patch
+class Float64List {
+  @patch
+  @pragma("vm:exact-result-type", _Float64List)
+  factory Float64List(int length) native "TypedData_Float64Array_new";
+
+  @patch
+  factory Float64List.fromList(List<double> elements) {
+    return new Float64List(elements.length)
+      ..setRange(0, elements.length, elements);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Float64List extends _TypedList
+    with _DoubleListMixin, _TypedDoubleListMixin<Float64List>
+    implements Float64List {
+  factory _Float64List._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  @pragma("vm:exact-result-type", "dart:core#_Double")
+  double operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedFloat64(index);
+  }
+
+  void operator []=(int index, double value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedFloat64(index, value);
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Float64List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Float64List _createList(int length) {
+    return new Float64List(length);
+  }
+
+  double _getIndexedFloat64(int index) {
+    return _getFloat64(index * Float64List.bytesPerElement);
+  }
+
+  void _setIndexedFloat64(int index, double value) {
+    _setFloat64(index * Float64List.bytesPerElement, value);
+  }
+}
+
+@patch
+class Float32x4List {
+  @patch
+  @pragma("vm:exact-result-type", _Float32x4List)
+  factory Float32x4List(int length) native "TypedData_Float32x4Array_new";
+
+  @patch
+  factory Float32x4List.fromList(List<Float32x4> elements) {
+    return new Float32x4List(elements.length)
+      ..setRange(0, elements.length, elements);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Float32x4List extends _TypedList
+    with _Float32x4ListMixin
+    implements Float32x4List {
+  factory _Float32x4List._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedFloat32x4(index);
+  }
+
+  void operator []=(int index, Float32x4 value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedFloat32x4(index, value);
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Float32x4List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Float32x4List _createList(int length) {
+    return new Float32x4List(length);
+  }
+
+  Float32x4 _getIndexedFloat32x4(int index) {
+    return _getFloat32x4(index * Float32x4List.bytesPerElement);
+  }
+
+  void _setIndexedFloat32x4(int index, Float32x4 value) {
+    _setFloat32x4(index * Float32x4List.bytesPerElement, value);
+  }
+}
+
+@patch
+class Int32x4List {
+  @patch
+  @pragma("vm:exact-result-type", _Int32x4List)
+  factory Int32x4List(int length) native "TypedData_Int32x4Array_new";
+
+  @patch
+  factory Int32x4List.fromList(List<Int32x4> elements) {
+    return new Int32x4List(elements.length)
+      ..setRange(0, elements.length, elements);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Int32x4List extends _TypedList
+    with _Int32x4ListMixin
+    implements Int32x4List {
+  factory _Int32x4List._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  @pragma("vm:exact-result-type", _Int32x4)
+  Int32x4 operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedInt32x4(index);
+  }
+
+  void operator []=(int index, Int32x4 value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedInt32x4(index, value);
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Int32x4List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Int32x4List _createList(int length) {
+    return new Int32x4List(length);
+  }
+
+  Int32x4 _getIndexedInt32x4(int index) {
+    return _getInt32x4(index * Int32x4List.bytesPerElement);
+  }
+
+  void _setIndexedInt32x4(int index, Int32x4 value) {
+    _setInt32x4(index * Int32x4List.bytesPerElement, value);
+  }
+}
+
+@patch
+class Float64x2List {
+  @patch
+  @pragma("vm:exact-result-type", _Float64x2List)
+  factory Float64x2List(int length) native "TypedData_Float64x2Array_new";
+
+  @patch
+  factory Float64x2List.fromList(List<Float64x2> elements) {
+    return new Float64x2List(elements.length)
+      ..setRange(0, elements.length, elements);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Float64x2List extends _TypedList
+    with _Float64x2ListMixin
+    implements Float64x2List {
+  factory _Float64x2List._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  @pragma("vm:exact-result-type", _Float64x2)
+  Float64x2 operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedFloat64x2(index);
+  }
+
+  void operator []=(int index, Float64x2 value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedFloat64x2(index, value);
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Float64x2List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Float64x2List _createList(int length) {
+    return new Float64x2List(length);
+  }
+
+  Float64x2 _getIndexedFloat64x2(int index) {
+    return _getFloat64x2(index * Float64x2List.bytesPerElement);
+  }
+
+  void _setIndexedFloat64x2(int index, Float64x2 value) {
+    _setFloat64x2(index * Float64x2List.bytesPerElement, value);
+  }
+}
+
+@pragma("vm:entry-point")
+class _ExternalInt8Array extends _TypedList
+    with _IntListMixin, _TypedIntListMixin<Int8List>
+    implements Int8List {
+  factory _ExternalInt8Array._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getInt8(index);
+  }
+
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setInt8(index, value);
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Int8List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Int8List _createList(int length) {
+    return new Int8List(length);
+  }
+}
+
+@pragma("vm:entry-point")
+class _ExternalUint8Array extends _TypedList
+    with _IntListMixin, _TypedIntListMixin<Uint8List>
+    implements Uint8List {
+  factory _ExternalUint8Array._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getUint8(index);
+  }
+
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setUint8(index, _toUint8(value));
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Uint8List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Uint8List _createList(int length) {
+    return new Uint8List(length);
+  }
+}
+
+@pragma("vm:entry-point")
+class _ExternalUint8ClampedArray extends _TypedList
+    with _IntListMixin, _TypedIntListMixin<Uint8ClampedList>
+    implements Uint8ClampedList {
+  factory _ExternalUint8ClampedArray._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getUint8(index);
+  }
+
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setUint8(index, _toClampedUint8(value));
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Uint8List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Uint8ClampedList _createList(int length) {
+    return new Uint8ClampedList(length);
+  }
+}
+
+@pragma("vm:entry-point")
+class _ExternalInt16Array extends _TypedList
+    with _IntListMixin, _TypedIntListMixin<Int16List>
+    implements Int16List {
+  factory _ExternalInt16Array._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedInt16(index);
+  }
+
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedInt16(index, _toInt16(value));
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Int16List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Int16List _createList(int length) {
+    return new Int16List(length);
+  }
+
+  int _getIndexedInt16(int index) {
+    return _getInt16(index * Int16List.bytesPerElement);
+  }
+
+  void _setIndexedInt16(int index, int value) {
+    _setInt16(index * Int16List.bytesPerElement, value);
+  }
+}
+
+@pragma("vm:entry-point")
+class _ExternalUint16Array extends _TypedList
+    with _IntListMixin, _TypedIntListMixin<Uint16List>
+    implements Uint16List {
+  factory _ExternalUint16Array._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedUint16(index);
+  }
+
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedUint16(index, _toUint16(value));
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Uint16List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Uint16List _createList(int length) {
+    return new Uint16List(length);
+  }
+
+  int _getIndexedUint16(int index) {
+    return _getUint16(index * Uint16List.bytesPerElement);
+  }
+
+  void _setIndexedUint16(int index, int value) {
+    _setUint16(index * Uint16List.bytesPerElement, value);
+  }
+}
+
+@pragma("vm:entry-point")
+class _ExternalInt32Array extends _TypedList
+    with _IntListMixin, _TypedIntListMixin<Int32List>
+    implements Int32List {
+  factory _ExternalInt32Array._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedInt32(index);
+  }
+
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedInt32(index, _toInt32(value));
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Int32List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Int32List _createList(int length) {
+    return new Int32List(length);
+  }
+
+  int _getIndexedInt32(int index) {
+    return _getInt32(index * Int32List.bytesPerElement);
+  }
+
+  void _setIndexedInt32(int index, int value) {
+    _setInt32(index * Int32List.bytesPerElement, value);
+  }
+}
+
+@pragma("vm:entry-point")
+class _ExternalUint32Array extends _TypedList
+    with _IntListMixin, _TypedIntListMixin<Uint32List>
+    implements Uint32List {
+  factory _ExternalUint32Array._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedUint32(index);
+  }
+
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedUint32(index, _toUint32(value));
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Uint32List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Uint32List _createList(int length) {
+    return new Uint32List(length);
+  }
+
+  int _getIndexedUint32(int index) {
+    return _getUint32(index * Uint32List.bytesPerElement);
+  }
+
+  void _setIndexedUint32(int index, int value) {
+    _setUint32(index * Uint32List.bytesPerElement, value);
+  }
+}
+
+@pragma("vm:entry-point")
+class _ExternalInt64Array extends _TypedList
+    with _IntListMixin, _TypedIntListMixin<Int64List>
+    implements Int64List {
+  factory _ExternalInt64Array._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedInt64(index);
+  }
+
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedInt64(index, value);
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Int64List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Int64List _createList(int length) {
+    return new Int64List(length);
+  }
+
+  int _getIndexedInt64(int index) {
+    return _getInt64(index * Int64List.bytesPerElement);
+  }
+
+  void _setIndexedInt64(int index, int value) {
+    _setInt64(index * Int64List.bytesPerElement, value);
+  }
+}
+
+@pragma("vm:entry-point")
+class _ExternalUint64Array extends _TypedList
+    with _IntListMixin, _TypedIntListMixin<Uint64List>
+    implements Uint64List {
+  factory _ExternalUint64Array._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedUint64(index);
+  }
+
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedUint64(index, value);
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Uint64List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Uint64List _createList(int length) {
+    return new Uint64List(length);
+  }
+
+  int _getIndexedUint64(int index) {
+    return _getUint64(index * Uint64List.bytesPerElement);
+  }
+
+  void _setIndexedUint64(int index, int value) {
+    _setUint64(index * Uint64List.bytesPerElement, value);
+  }
+}
+
+@pragma("vm:entry-point")
+class _ExternalFloat32Array extends _TypedList
+    with _DoubleListMixin, _TypedDoubleListMixin<Float32List>
+    implements Float32List {
+  factory _ExternalFloat32Array._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  double operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedFloat32(index);
+  }
+
+  void operator []=(int index, double value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedFloat32(index, value);
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Float32List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Float32List _createList(int length) {
+    return new Float32List(length);
+  }
+
+  double _getIndexedFloat32(int index) {
+    return _getFloat32(index * Float32List.bytesPerElement);
+  }
+
+  void _setIndexedFloat32(int index, double value) {
+    _setFloat32(index * Float32List.bytesPerElement, value);
+  }
+}
+
+@pragma("vm:entry-point")
+class _ExternalFloat64Array extends _TypedList
+    with _DoubleListMixin, _TypedDoubleListMixin<Float64List>
+    implements Float64List {
+  factory _ExternalFloat64Array._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  double operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedFloat64(index);
+  }
+
+  void operator []=(int index, double value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedFloat64(index, value);
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Float64List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Float64List _createList(int length) {
+    return new Float64List(length);
+  }
+
+  double _getIndexedFloat64(int index) {
+    return _getFloat64(index * Float64List.bytesPerElement);
+  }
+
+  void _setIndexedFloat64(int index, double value) {
+    _setFloat64(index * Float64List.bytesPerElement, value);
+  }
+}
+
+@pragma("vm:entry-point")
+class _ExternalFloat32x4Array extends _TypedList
+    with _Float32x4ListMixin
+    implements Float32x4List {
+  factory _ExternalFloat32x4Array._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  Float32x4 operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedFloat32x4(index);
+  }
+
+  void operator []=(int index, Float32x4 value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedFloat32x4(index, value);
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Float32x4List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Float32x4List _createList(int length) {
+    return new Float32x4List(length);
+  }
+
+  Float32x4 _getIndexedFloat32x4(int index) {
+    return _getFloat32x4(index * Float32x4List.bytesPerElement);
+  }
+
+  void _setIndexedFloat32x4(int index, Float32x4 value) {
+    _setFloat32x4(index * Float32x4List.bytesPerElement, value);
+  }
+}
+
+@pragma("vm:entry-point")
+class _ExternalInt32x4Array extends _TypedList
+    with _Int32x4ListMixin
+    implements Int32x4List {
+  factory _ExternalInt32x4Array._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  Int32x4 operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedInt32x4(index);
+  }
+
+  void operator []=(int index, Int32x4 value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedInt32x4(index, value);
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Int32x4List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Int32x4List _createList(int length) {
+    return new Int32x4List(length);
+  }
+
+  Int32x4 _getIndexedInt32x4(int index) {
+    return _getInt32x4(index * Int32x4List.bytesPerElement);
+  }
+
+  void _setIndexedInt32x4(int index, Int32x4 value) {
+    _setInt32x4(index * Int32x4List.bytesPerElement, value);
+  }
+}
+
+@pragma("vm:entry-point")
+class _ExternalFloat64x2Array extends _TypedList
+    with _Float64x2ListMixin
+    implements Float64x2List {
+  factory _ExternalFloat64x2Array._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  // Method(s) implementing the List interface.
+  Float64x2 operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _getIndexedFloat64x2(index);
+  }
+
+  void operator []=(int index, Float64x2 value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _setIndexedFloat64x2(index, value);
+  }
+
+  // Method(s) implementing the TypedData interface.
+  int get elementSizeInBytes {
+    return Float64x2List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Float64x2List _createList(int length) {
+    return new Float64x2List(length);
+  }
+
+  Float64x2 _getIndexedFloat64x2(int index) {
+    return _getFloat64x2(index * Float64x2List.bytesPerElement);
+  }
+
+  void _setIndexedFloat64x2(int index, Float64x2 value) {
+    _setFloat64x2(index * Float64x2List.bytesPerElement, value);
+  }
+}
+
+@patch
+class Float32x4 {
+  @patch
+  @pragma("vm:exact-result-type", _Float32x4)
+  factory Float32x4(double x, double y, double z, double w)
+      native "Float32x4_fromDoubles";
+
+  @patch
+  @pragma("vm:exact-result-type", _Float32x4)
+  factory Float32x4.splat(double v) native "Float32x4_splat";
+
+  @patch
+  @pragma("vm:exact-result-type", _Float32x4)
+  factory Float32x4.zero() native "Float32x4_zero";
+
+  @patch
+  @pragma("vm:exact-result-type", _Float32x4)
+  factory Float32x4.fromInt32x4Bits(Int32x4 x)
+      native "Float32x4_fromInt32x4Bits";
+
+  @patch
+  @pragma("vm:exact-result-type", _Float32x4)
+  factory Float32x4.fromFloat64x2(Float64x2 v) native "Float32x4_fromFloat64x2";
+}
+
+@pragma("vm:entry-point")
+class _Float32x4 implements Float32x4 {
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 operator +(Float32x4 other) native "Float32x4_add";
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 operator -() native "Float32x4_negate";
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 operator -(Float32x4 other) native "Float32x4_sub";
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 operator *(Float32x4 other) native "Float32x4_mul";
+  Float32x4 operator /(Float32x4 other) native "Float32x4_div";
+  @pragma("vm:exact-result-type", _Int32x4)
+  Int32x4 lessThan(Float32x4 other) native "Float32x4_cmplt";
+  @pragma("vm:exact-result-type", _Int32x4)
+  Int32x4 lessThanOrEqual(Float32x4 other) native "Float32x4_cmplte";
+  @pragma("vm:exact-result-type", _Int32x4)
+  Int32x4 greaterThan(Float32x4 other) native "Float32x4_cmpgt";
+  @pragma("vm:exact-result-type", _Int32x4)
+  Int32x4 greaterThanOrEqual(Float32x4 other) native "Float32x4_cmpgte";
+  @pragma("vm:exact-result-type", _Int32x4)
+  Int32x4 equal(Float32x4 other) native "Float32x4_cmpequal";
+  @pragma("vm:exact-result-type", _Int32x4)
+  Int32x4 notEqual(Float32x4 other) native "Float32x4_cmpnequal";
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 scale(double s) native "Float32x4_scale";
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 abs() native "Float32x4_abs";
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 clamp(Float32x4 lowerLimit, Float32x4 upperLimit)
+      native "Float32x4_clamp";
+  @pragma("vm:exact-result-type", "dart:core#_Double")
+  double get x native "Float32x4_getX";
+  @pragma("vm:exact-result-type", "dart:core#_Double")
+  double get y native "Float32x4_getY";
+  @pragma("vm:exact-result-type", "dart:core#_Double")
+  double get z native "Float32x4_getZ";
+  @pragma("vm:exact-result-type", "dart:core#_Double")
+  double get w native "Float32x4_getW";
+  int get signMask native "Float32x4_getSignMask";
+
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 shuffle(int mask) native "Float32x4_shuffle";
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 shuffleMix(Float32x4 zw, int mask) native "Float32x4_shuffleMix";
+
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 withX(double x) native "Float32x4_setX";
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 withY(double y) native "Float32x4_setY";
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 withZ(double z) native "Float32x4_setZ";
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 withW(double w) native "Float32x4_setW";
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 min(Float32x4 other) native "Float32x4_min";
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 max(Float32x4 other) native "Float32x4_max";
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 sqrt() native "Float32x4_sqrt";
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 reciprocal() native "Float32x4_reciprocal";
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 reciprocalSqrt() native "Float32x4_reciprocalSqrt";
+}
+
+@patch
+class Int32x4 {
+  @patch
+  @pragma("vm:exact-result-type", _Int32x4)
+  factory Int32x4(int x, int y, int z, int w) native "Int32x4_fromInts";
+
+  @patch
+  @pragma("vm:exact-result-type", _Int32x4)
+  factory Int32x4.bool(bool x, bool y, bool z, bool w)
+      native "Int32x4_fromBools";
+
+  @patch
+  @pragma("vm:exact-result-type", _Int32x4)
+  factory Int32x4.fromFloat32x4Bits(Float32x4 x)
+      native "Int32x4_fromFloat32x4Bits";
+}
+
+@pragma("vm:entry-point")
+class _Int32x4 implements Int32x4 {
+  Int32x4 operator |(Int32x4 other) native "Int32x4_or";
+  Int32x4 operator &(Int32x4 other) native "Int32x4_and";
+  Int32x4 operator ^(Int32x4 other) native "Int32x4_xor";
+  Int32x4 operator +(Int32x4 other) native "Int32x4_add";
+  Int32x4 operator -(Int32x4 other) native "Int32x4_sub";
+  int get x native "Int32x4_getX";
+  int get y native "Int32x4_getY";
+  int get z native "Int32x4_getZ";
+  int get w native "Int32x4_getW";
+  int get signMask native "Int32x4_getSignMask";
+  @pragma("vm:exact-result-type", _Int32x4)
+  Int32x4 shuffle(int mask) native "Int32x4_shuffle";
+  @pragma("vm:exact-result-type", _Int32x4)
+  Int32x4 shuffleMix(Int32x4 zw, int mask) native "Int32x4_shuffleMix";
+  Int32x4 withX(int x) native "Int32x4_setX";
+  Int32x4 withY(int y) native "Int32x4_setY";
+  Int32x4 withZ(int z) native "Int32x4_setZ";
+  Int32x4 withW(int w) native "Int32x4_setW";
+  @pragma("vm:exact-result-type", bool)
+  bool get flagX native "Int32x4_getFlagX";
+  @pragma("vm:exact-result-type", bool)
+  bool get flagY native "Int32x4_getFlagY";
+  @pragma("vm:exact-result-type", bool)
+  bool get flagZ native "Int32x4_getFlagZ";
+  @pragma("vm:exact-result-type", bool)
+  bool get flagW native "Int32x4_getFlagW";
+  @pragma("vm:exact-result-type", _Int32x4)
+  Int32x4 withFlagX(bool x) native "Int32x4_setFlagX";
+  @pragma("vm:exact-result-type", _Int32x4)
+  Int32x4 withFlagY(bool y) native "Int32x4_setFlagY";
+  @pragma("vm:exact-result-type", _Int32x4)
+  Int32x4 withFlagZ(bool z) native "Int32x4_setFlagZ";
+  @pragma("vm:exact-result-type", _Int32x4)
+  Int32x4 withFlagW(bool w) native "Int32x4_setFlagW";
+  @pragma("vm:exact-result-type", _Float32x4)
+  Float32x4 select(Float32x4 trueValue, Float32x4 falseValue)
+      native "Int32x4_select";
+}
+
+@patch
+class Float64x2 {
+  @patch
+  @pragma("vm:exact-result-type", _Float64x2)
+  factory Float64x2(double x, double y) native "Float64x2_fromDoubles";
+
+  @patch
+  @pragma("vm:exact-result-type", _Float64x2)
+  factory Float64x2.splat(double v) native "Float64x2_splat";
+
+  @patch
+  @pragma("vm:exact-result-type", _Float64x2)
+  factory Float64x2.zero() native "Float64x2_zero";
+
+  @patch
+  @pragma("vm:exact-result-type", _Float64x2)
+  factory Float64x2.fromFloat32x4(Float32x4 v) native "Float64x2_fromFloat32x4";
+}
+
+@pragma("vm:entry-point")
+class _Float64x2 implements Float64x2 {
+  Float64x2 operator +(Float64x2 other) native "Float64x2_add";
+  @pragma("vm:exact-result-type", _Float64x2)
+  Float64x2 operator -() native "Float64x2_negate";
+  Float64x2 operator -(Float64x2 other) native "Float64x2_sub";
+  Float64x2 operator *(Float64x2 other) native "Float64x2_mul";
+  Float64x2 operator /(Float64x2 other) native "Float64x2_div";
+  @pragma("vm:exact-result-type", _Float64x2)
+  Float64x2 scale(double s) native "Float64x2_scale";
+  @pragma("vm:exact-result-type", _Float64x2)
+  Float64x2 abs() native "Float64x2_abs";
+  Float64x2 clamp(Float64x2 lowerLimit, Float64x2 upperLimit)
+      native "Float64x2_clamp";
+  @pragma("vm:exact-result-type", "dart:core#_Double")
+  double get x native "Float64x2_getX";
+  @pragma("vm:exact-result-type", "dart:core#_Double")
+  double get y native "Float64x2_getY";
+  int get signMask native "Float64x2_getSignMask";
+  @pragma("vm:exact-result-type", _Float64x2)
+  Float64x2 withX(double x) native "Float64x2_setX";
+  @pragma("vm:exact-result-type", _Float64x2)
+  Float64x2 withY(double y) native "Float64x2_setY";
+  @pragma("vm:exact-result-type", _Float64x2)
+  Float64x2 min(Float64x2 other) native "Float64x2_min";
+  @pragma("vm:exact-result-type", _Float64x2)
+  Float64x2 max(Float64x2 other) native "Float64x2_max";
+  @pragma("vm:exact-result-type", _Float64x2)
+  Float64x2 sqrt() native "Float64x2_sqrt";
+}
+
+class _TypedListIterator<E> implements Iterator<E> {
+  final List<E> _array;
+  final int _length;
+  int _position;
+  E _current;
+
+  _TypedListIterator(List array)
+      : _array = array,
+        _length = array.length,
+        _position = -1 {
+    assert(array is _TypedList || array is _TypedListView);
+  }
+
+  bool moveNext() {
+    int nextPosition = _position + 1;
+    if (nextPosition < _length) {
+      _current = _array[nextPosition];
+      _position = nextPosition;
+      return true;
+    }
+    _position = _length;
+    _current = null;
+    return false;
+  }
+
+  E get current => _current;
+}
+
+abstract class _TypedListView extends _TypedListBase implements TypedData {
+  // Method(s) implementing the TypedData interface.
+
+  int get lengthInBytes {
+    return length * elementSizeInBytes;
+  }
+
+  _ByteBuffer get buffer {
+    return _typedData.buffer;
+  }
+
+  @pragma("vm:non-nullable-result-type")
+  @pragma("vm:prefer-inline")
+  _TypedList get _typedData native "TypedDataView_typedData";
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  @pragma("vm:prefer-inline")
+  int get offsetInBytes native "TypedDataView_offsetInBytes";
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  @pragma("vm:prefer-inline")
+  int get length native "TypedDataView_length";
+}
+
+@pragma("vm:entry-point")
+class _Int8ArrayView extends _TypedListView
+    with _IntListMixin, _TypedIntListMixin<Int8List>
+    implements Int8List {
+  // Constructor.
+  @pragma("vm:exact-result-type", _Int8ArrayView)
+  factory _Int8ArrayView._(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Int8ArrayView_new";
+
+  // Method(s) implementing List interface.
+  @pragma("vm:prefer-inline")
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _typedData
+        ._getInt8(offsetInBytes + (index * Int8List.bytesPerElement));
+  }
+
+  @pragma("vm:prefer-inline")
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _typedData._setInt8(
+        offsetInBytes + (index * Int8List.bytesPerElement), _toInt8(value));
+  }
+
+  // Method(s) implementing TypedData interface.
+  int get elementSizeInBytes {
+    return Int8List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Int8List _createList(int length) {
+    return new Int8List(length);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Uint8ArrayView extends _TypedListView
+    with _IntListMixin, _TypedIntListMixin<Uint8List>
+    implements Uint8List {
+  // Constructor.
+  @pragma("vm:exact-result-type", _Uint8ArrayView)
+  factory _Uint8ArrayView._(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Uint8ArrayView_new";
+
+  // Method(s) implementing List interface.
+  @pragma("vm:prefer-inline")
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _typedData
+        ._getUint8(offsetInBytes + (index * Uint8List.bytesPerElement));
+  }
+
+  @pragma("vm:prefer-inline")
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _typedData._setUint8(
+        offsetInBytes + (index * Uint8List.bytesPerElement), _toUint8(value));
+  }
+
+  // Method(s) implementing TypedData interface.
+  int get elementSizeInBytes {
+    return Uint8List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Uint8List _createList(int length) {
+    return new Uint8List(length);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Uint8ClampedArrayView extends _TypedListView
+    with _IntListMixin, _TypedIntListMixin<Uint8ClampedList>
+    implements Uint8ClampedList {
+  // Constructor.
+  @pragma("vm:exact-result-type", _Uint8ClampedArrayView)
+  factory _Uint8ClampedArrayView._(_TypedList buffer, int offsetInBytes,
+      int length) native "TypedDataView_Uint8ClampedArrayView_new";
+
+  // Method(s) implementing List interface.
+  @pragma("vm:prefer-inline")
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _typedData
+        ._getUint8(offsetInBytes + (index * Uint8List.bytesPerElement));
+  }
+
+  @pragma("vm:prefer-inline")
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _typedData._setUint8(offsetInBytes + (index * Uint8List.bytesPerElement),
+        _toClampedUint8(value));
+  }
+
+  // Method(s) implementing TypedData interface.
+  int get elementSizeInBytes {
+    return Uint8List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Uint8ClampedList _createList(int length) {
+    return new Uint8ClampedList(length);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Int16ArrayView extends _TypedListView
+    with _IntListMixin, _TypedIntListMixin<Int16List>
+    implements Int16List {
+  // Constructor.
+  @pragma("vm:exact-result-type", _Int16ArrayView)
+  factory _Int16ArrayView._(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Int16ArrayView_new";
+
+  // Method(s) implementing List interface.
+  @pragma("vm:prefer-inline")
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _typedData
+        ._getInt16(offsetInBytes + (index * Int16List.bytesPerElement));
+  }
+
+  @pragma("vm:prefer-inline")
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _typedData._setInt16(
+        offsetInBytes + (index * Int16List.bytesPerElement), _toInt16(value));
+  }
+
+  void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) {
+    if (iterable is CodeUnits) {
+      end = RangeError.checkValidRange(start, end, this.length);
+      int length = end - start;
+      int byteStart = this.offsetInBytes + start * Int16List.bytesPerElement;
+      _typedData._setCodeUnits(iterable, byteStart, length, skipCount);
+    } else {
+      super.setRange(start, end, iterable, skipCount);
+    }
+  }
+
+  // Method(s) implementing TypedData interface.
+
+  int get elementSizeInBytes {
+    return Int16List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Int16List _createList(int length) {
+    return new Int16List(length);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Uint16ArrayView extends _TypedListView
+    with _IntListMixin, _TypedIntListMixin<Uint16List>
+    implements Uint16List {
+  // Constructor.
+  @pragma("vm:exact-result-type", _Uint16ArrayView)
+  factory _Uint16ArrayView._(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Uint16ArrayView_new";
+
+  // Method(s) implementing List interface.
+  @pragma("vm:prefer-inline")
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _typedData
+        ._getUint16(offsetInBytes + (index * Uint16List.bytesPerElement));
+  }
+
+  @pragma("vm:prefer-inline")
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _typedData._setUint16(
+        offsetInBytes + (index * Uint16List.bytesPerElement), _toUint16(value));
+  }
+
+  void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) {
+    if (iterable is CodeUnits) {
+      end = RangeError.checkValidRange(start, end, this.length);
+      int length = end - start;
+      int byteStart = this.offsetInBytes + start * Uint16List.bytesPerElement;
+      _typedData._setCodeUnits(iterable, byteStart, length, skipCount);
+    } else {
+      super.setRange(start, end, iterable, skipCount);
+    }
+  }
+
+  // Method(s) implementing TypedData interface.
+
+  int get elementSizeInBytes {
+    return Uint16List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+
+  Uint16List _createList(int length) {
+    return new Uint16List(length);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Int32ArrayView extends _TypedListView
+    with _IntListMixin, _TypedIntListMixin<Int32List>
+    implements Int32List {
+  // Constructor.
+  @pragma("vm:exact-result-type", _Int32ArrayView)
+  factory _Int32ArrayView._(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Int32ArrayView_new";
+
+  // Method(s) implementing List interface.
+  @pragma("vm:prefer-inline")
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _typedData
+        ._getInt32(offsetInBytes + (index * Int32List.bytesPerElement));
+  }
+
+  @pragma("vm:prefer-inline")
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _typedData._setInt32(
+        offsetInBytes + (index * Int32List.bytesPerElement), _toInt32(value));
+  }
+
+  // Method(s) implementing TypedData interface.
+  int get elementSizeInBytes {
+    return Int32List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Int32List _createList(int length) {
+    return new Int32List(length);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Uint32ArrayView extends _TypedListView
+    with _IntListMixin, _TypedIntListMixin<Uint32List>
+    implements Uint32List {
+  // Constructor.
+  @pragma("vm:exact-result-type", _Uint32ArrayView)
+  factory _Uint32ArrayView._(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Uint32ArrayView_new";
+
+  // Method(s) implementing List interface.
+  @pragma("vm:prefer-inline")
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _typedData
+        ._getUint32(offsetInBytes + (index * Uint32List.bytesPerElement));
+  }
+
+  @pragma("vm:prefer-inline")
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _typedData._setUint32(
+        offsetInBytes + (index * Uint32List.bytesPerElement), _toUint32(value));
+  }
+
+  // Method(s) implementing TypedData interface.
+  int get elementSizeInBytes {
+    return Uint32List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Uint32List _createList(int length) {
+    return new Uint32List(length);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Int64ArrayView extends _TypedListView
+    with _IntListMixin, _TypedIntListMixin<Int64List>
+    implements Int64List {
+  // Constructor.
+  @pragma("vm:exact-result-type", _Int64ArrayView)
+  factory _Int64ArrayView._(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Int64ArrayView_new";
+
+  // Method(s) implementing List interface.
+  @pragma("vm:prefer-inline")
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _typedData
+        ._getInt64(offsetInBytes + (index * Int64List.bytesPerElement));
+  }
+
+  @pragma("vm:prefer-inline")
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _typedData._setInt64(
+        offsetInBytes + (index * Int64List.bytesPerElement), value);
+  }
+
+  // Method(s) implementing TypedData interface.
+  int get elementSizeInBytes {
+    return Int64List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Int64List _createList(int length) {
+    return new Int64List(length);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Uint64ArrayView extends _TypedListView
+    with _IntListMixin, _TypedIntListMixin<Uint64List>
+    implements Uint64List {
+  // Constructor.
+  @pragma("vm:exact-result-type", _Uint64ArrayView)
+  factory _Uint64ArrayView._(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Uint64ArrayView_new";
+
+  // Method(s) implementing List interface.
+  @pragma("vm:prefer-inline")
+  int operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _typedData
+        ._getUint64(offsetInBytes + (index * Uint64List.bytesPerElement));
+  }
+
+  @pragma("vm:prefer-inline")
+  void operator []=(int index, int value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _typedData._setUint64(
+        offsetInBytes + (index * Uint64List.bytesPerElement), value);
+  }
+
+  // Method(s) implementing TypedData interface.
+  int get elementSizeInBytes {
+    return Uint64List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Uint64List _createList(int length) {
+    return new Uint64List(length);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Float32ArrayView extends _TypedListView
+    with _DoubleListMixin, _TypedDoubleListMixin<Float32List>
+    implements Float32List {
+  // Constructor.
+  @pragma("vm:exact-result-type", _Float32ArrayView)
+  factory _Float32ArrayView._(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Float32ArrayView_new";
+
+  // Method(s) implementing List interface.
+  @pragma("vm:prefer-inline")
+  double operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _typedData
+        ._getFloat32(offsetInBytes + (index * Float32List.bytesPerElement));
+  }
+
+  @pragma("vm:prefer-inline")
+  void operator []=(int index, double value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _typedData._setFloat32(
+        offsetInBytes + (index * Float32List.bytesPerElement), value);
+  }
+
+  // Method(s) implementing TypedData interface.
+  int get elementSizeInBytes {
+    return Float32List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Float32List _createList(int length) {
+    return new Float32List(length);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Float64ArrayView extends _TypedListView
+    with _DoubleListMixin, _TypedDoubleListMixin<Float64List>
+    implements Float64List {
+  // Constructor.
+  @pragma("vm:exact-result-type", _Float64ArrayView)
+  factory _Float64ArrayView._(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Float64ArrayView_new";
+
+  // Method(s) implementing List interface.
+  @pragma("vm:prefer-inline")
+  double operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _typedData
+        ._getFloat64(offsetInBytes + (index * Float64List.bytesPerElement));
+  }
+
+  @pragma("vm:prefer-inline")
+  void operator []=(int index, double value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _typedData._setFloat64(
+        offsetInBytes + (index * Float64List.bytesPerElement), value);
+  }
+
+  // Method(s) implementing TypedData interface.
+  int get elementSizeInBytes {
+    return Float64List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Float64List _createList(int length) {
+    return new Float64List(length);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Float32x4ArrayView extends _TypedListView
+    with _Float32x4ListMixin
+    implements Float32x4List {
+  // Constructor.
+  @pragma("vm:exact-result-type", _Float32x4ArrayView)
+  factory _Float32x4ArrayView._(_TypedList buffer, int offsetInBytes,
+      int length) native "TypedDataView_Float32x4ArrayView_new";
+
+  // Method(s) implementing List interface.
+  Float32x4 operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _typedData
+        ._getFloat32x4(offsetInBytes + (index * Float32x4List.bytesPerElement));
+  }
+
+  void operator []=(int index, Float32x4 value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _typedData._setFloat32x4(
+        offsetInBytes + (index * Float32x4List.bytesPerElement), value);
+  }
+
+  // Method(s) implementing TypedData interface.
+  int get elementSizeInBytes {
+    return Float32x4List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Float32x4List _createList(int length) {
+    return new Float32x4List(length);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Int32x4ArrayView extends _TypedListView
+    with _Int32x4ListMixin
+    implements Int32x4List {
+  // Constructor.
+  @pragma("vm:exact-result-type", _Int32x4ArrayView)
+  factory _Int32x4ArrayView._(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_Int32x4ArrayView_new";
+
+  // Method(s) implementing List interface.
+  Int32x4 operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _typedData
+        ._getInt32x4(offsetInBytes + (index * Int32x4List.bytesPerElement));
+  }
+
+  void operator []=(int index, Int32x4 value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _typedData._setInt32x4(
+        offsetInBytes + (index * Int32x4List.bytesPerElement), value);
+  }
+
+  // Method(s) implementing TypedData interface.
+  int get elementSizeInBytes {
+    return Int32x4List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Int32x4List _createList(int length) {
+    return new Int32x4List(length);
+  }
+}
+
+@pragma("vm:entry-point")
+class _Float64x2ArrayView extends _TypedListView
+    with _Float64x2ListMixin
+    implements Float64x2List {
+  // Constructor.
+  @pragma("vm:exact-result-type", _Float64x2ArrayView)
+  factory _Float64x2ArrayView._(_TypedList buffer, int offsetInBytes,
+      int length) native "TypedDataView_Float64x2ArrayView_new";
+
+  // Method(s) implementing List interface.
+  Float64x2 operator [](int index) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    return _typedData
+        ._getFloat64x2(offsetInBytes + (index * Float64x2List.bytesPerElement));
+  }
+
+  void operator []=(int index, Float64x2 value) {
+    if (index < 0 || index >= length) {
+      throw new RangeError.index(index, this, "index");
+    }
+    _typedData._setFloat64x2(
+        offsetInBytes + (index * Float64x2List.bytesPerElement), value);
+  }
+
+  // Method(s) implementing TypedData interface.
+  int get elementSizeInBytes {
+    return Float64x2List.bytesPerElement;
+  }
+
+  // Internal utility methods.
+  Float64x2List _createList(int length) {
+    return new Float64x2List(length);
+  }
+}
+
+@pragma("vm:entry-point")
+class _ByteDataView implements ByteData {
+  @pragma("vm:exact-result-type", _ByteDataView)
+  factory _ByteDataView._(_TypedList buffer, int offsetInBytes, int length)
+      native "TypedDataView_ByteDataView_new";
+
+  // Method(s) implementing TypedData interface.
+  _ByteBuffer get buffer {
+    return _typedData.buffer;
+  }
+
+  int get lengthInBytes {
+    return length;
+  }
+
+  int get elementSizeInBytes {
+    return 1;
+  }
+
+  // Method(s) implementing ByteData interface.
+
+  @pragma("vm:prefer-inline")
+  int getInt8(int byteOffset) {
+    if (byteOffset < 0 || byteOffset >= length) {
+      throw new RangeError.index(byteOffset, this, "byteOffset");
+    }
+    return _typedData._getInt8(offsetInBytes + byteOffset);
+  }
+
+  @pragma("vm:prefer-inline")
+  void setInt8(int byteOffset, int value) {
+    if (byteOffset < 0 || byteOffset >= length) {
+      throw new RangeError.index(byteOffset, this, "byteOffset");
+    }
+    _typedData._setInt8(offsetInBytes + byteOffset, value);
+  }
+
+  @pragma("vm:prefer-inline")
+  int getUint8(int byteOffset) {
+    if (byteOffset < 0 || byteOffset >= length) {
+      throw new RangeError.index(byteOffset, this, "byteOffset");
+    }
+    return _typedData._getUint8(offsetInBytes + byteOffset);
+  }
+
+  @pragma("vm:prefer-inline")
+  void setUint8(int byteOffset, int value) {
+    if (byteOffset < 0 || byteOffset >= length) {
+      throw new RangeError.index(byteOffset, this, "byteOffset");
+    }
+    _typedData._setUint8(offsetInBytes + byteOffset, value);
+  }
+
+  @pragma("vm:prefer-inline")
+  int getInt16(int byteOffset, [Endian endian = Endian.big]) {
+    if (byteOffset < 0 || byteOffset + 1 >= length) {
+      throw new RangeError.range(byteOffset, 0, length - 2, "byteOffset");
+    }
+    var result = _typedData._getInt16(offsetInBytes + byteOffset);
+    if (identical(endian, Endian.host)) {
+      return result;
+    }
+    return _byteSwap16(result).toSigned(16);
+  }
+
+  @pragma("vm:prefer-inline")
+  void setInt16(int byteOffset, int value, [Endian endian = Endian.big]) {
+    if (byteOffset < 0 || byteOffset + 1 >= length) {
+      throw new RangeError.range(byteOffset, 0, length - 2, "byteOffset");
+    }
+    _typedData._setInt16(offsetInBytes + byteOffset,
+        identical(endian, Endian.host) ? value : _byteSwap16(value));
+  }
+
+  @pragma("vm:prefer-inline")
+  int getUint16(int byteOffset, [Endian endian = Endian.big]) {
+    if (byteOffset < 0 || byteOffset + 1 >= length) {
+      throw new RangeError.range(byteOffset, 0, length - 2, "byteOffset");
+    }
+    var result = _typedData._getUint16(offsetInBytes + byteOffset);
+    if (identical(endian, Endian.host)) {
+      return result;
+    }
+    return _byteSwap16(result);
+  }
+
+  @pragma("vm:prefer-inline")
+  void setUint16(int byteOffset, int value, [Endian endian = Endian.big]) {
+    if (byteOffset < 0 || byteOffset + 1 >= length) {
+      throw new RangeError.range(byteOffset, 0, length - 2, "byteOffset");
+    }
+    _typedData._setUint16(offsetInBytes + byteOffset,
+        identical(endian, Endian.host) ? value : _byteSwap16(value));
+  }
+
+  @pragma("vm:prefer-inline")
+  int getInt32(int byteOffset, [Endian endian = Endian.big]) {
+    if (byteOffset < 0 || byteOffset + 3 >= length) {
+      throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
+    }
+    var result = _typedData._getInt32(offsetInBytes + byteOffset);
+    if (identical(endian, Endian.host)) {
+      return result;
+    }
+    return _byteSwap32(result).toSigned(32);
+  }
+
+  @pragma("vm:prefer-inline")
+  void setInt32(int byteOffset, int value, [Endian endian = Endian.big]) {
+    if (byteOffset < 0 || byteOffset + 3 >= length) {
+      throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
+    }
+    _typedData._setInt32(offsetInBytes + byteOffset,
+        identical(endian, Endian.host) ? value : _byteSwap32(value));
+  }
+
+  @pragma("vm:prefer-inline")
+  int getUint32(int byteOffset, [Endian endian = Endian.big]) {
+    if (byteOffset < 0 || byteOffset + 3 >= length) {
+      throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
+    }
+    var result = _typedData._getUint32(offsetInBytes + byteOffset);
+    if (identical(endian, Endian.host)) {
+      return result;
+    }
+    return _byteSwap32(result);
+  }
+
+  @pragma("vm:prefer-inline")
+  void setUint32(int byteOffset, int value, [Endian endian = Endian.big]) {
+    if (byteOffset < 0 || byteOffset + 3 >= length) {
+      throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
+    }
+    _typedData._setUint32(offsetInBytes + byteOffset,
+        identical(endian, Endian.host) ? value : _byteSwap32(value));
+  }
+
+  @pragma("vm:prefer-inline")
+  int getInt64(int byteOffset, [Endian endian = Endian.big]) {
+    if (byteOffset < 0 || byteOffset + 7 >= length) {
+      throw new RangeError.range(byteOffset, 0, length - 8, "byteOffset");
+    }
+    var result = _typedData._getInt64(offsetInBytes + byteOffset);
+    if (identical(endian, Endian.host)) {
+      return result;
+    }
+    return _byteSwap64(result).toSigned(64);
+  }
+
+  @pragma("vm:prefer-inline")
+  void setInt64(int byteOffset, int value, [Endian endian = Endian.big]) {
+    if (byteOffset < 0 || byteOffset + 7 >= length) {
+      throw new RangeError.range(byteOffset, 0, length - 8, "byteOffset");
+    }
+    _typedData._setInt64(offsetInBytes + byteOffset,
+        identical(endian, Endian.host) ? value : _byteSwap64(value));
+  }
+
+  @pragma("vm:prefer-inline")
+  int getUint64(int byteOffset, [Endian endian = Endian.big]) {
+    if (byteOffset < 0 || byteOffset + 7 >= length) {
+      throw new RangeError.range(byteOffset, 0, length - 8, "byteOffset");
+    }
+    var result = _typedData._getUint64(offsetInBytes + byteOffset);
+    if (identical(endian, Endian.host)) {
+      return result;
+    }
+    return _byteSwap64(result);
+  }
+
+  @pragma("vm:prefer-inline")
+  void setUint64(int byteOffset, int value, [Endian endian = Endian.big]) {
+    if (byteOffset < 0 || byteOffset + 7 >= length) {
+      throw new RangeError.range(byteOffset, 0, length - 8, "byteOffset");
+    }
+    _typedData._setUint64(offsetInBytes + byteOffset,
+        identical(endian, Endian.host) ? value : _byteSwap64(value));
+  }
+
+  @pragma("vm:prefer-inline")
+  double getFloat32(int byteOffset, [Endian endian = Endian.big]) {
+    if (byteOffset < 0 || byteOffset + 3 >= length) {
+      throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
+    }
+    if (identical(endian, Endian.host)) {
+      return _typedData._getFloat32(offsetInBytes + byteOffset);
+    }
+    _convU32[0] =
+        _byteSwap32(_typedData._getUint32(offsetInBytes + byteOffset));
+    return _convF32[0];
+  }
+
+  @pragma("vm:prefer-inline")
+  void setFloat32(int byteOffset, double value, [Endian endian = Endian.big]) {
+    if (byteOffset < 0 || byteOffset + 3 >= length) {
+      throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
+    }
+    if (identical(endian, Endian.host)) {
+      _typedData._setFloat32(offsetInBytes + byteOffset, value);
+      return;
+    }
+    _convF32[0] = value;
+    _typedData._setUint32(offsetInBytes + byteOffset, _byteSwap32(_convU32[0]));
+  }
+
+  @pragma("vm:prefer-inline")
+  double getFloat64(int byteOffset, [Endian endian = Endian.big]) {
+    if (byteOffset < 0 || byteOffset + 7 >= length) {
+      throw new RangeError.range(byteOffset, 0, length - 8, "byteOffset");
+    }
+    if (identical(endian, Endian.host)) {
+      return _typedData._getFloat64(offsetInBytes + byteOffset);
+    }
+    _convU64[0] =
+        _byteSwap64(_typedData._getUint64(offsetInBytes + byteOffset));
+    return _convF64[0];
+  }
+
+  @pragma("vm:prefer-inline")
+  void setFloat64(int byteOffset, double value, [Endian endian = Endian.big]) {
+    if (byteOffset < 0 || byteOffset + 7 >= length) {
+      throw new RangeError.range(byteOffset, 0, length - 8, "byteOffset");
+    }
+    if (identical(endian, Endian.host)) {
+      _typedData._setFloat64(offsetInBytes + byteOffset, value);
+      return;
+    }
+    _convF64[0] = value;
+    _typedData._setUint64(offsetInBytes + byteOffset, _byteSwap64(_convU64[0]));
+  }
+
+  Float32x4 getFloat32x4(int byteOffset, [Endian endian = Endian.big]) {
+    if (byteOffset < 0 || byteOffset + 3 >= length) {
+      throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
+    }
+    // TODO(johnmccutchan) : Need to resolve this for endianity.
+    return _typedData._getFloat32x4(offsetInBytes + byteOffset);
+  }
+
+  void setFloat32x4(int byteOffset, Float32x4 value,
+      [Endian endian = Endian.big]) {
+    if (byteOffset < 0 || byteOffset + 3 >= length) {
+      throw new RangeError.range(byteOffset, 0, length - 4, "byteOffset");
+    }
+    // TODO(johnmccutchan) : Need to resolve this for endianity.
+    _typedData._setFloat32x4(offsetInBytes + byteOffset, value);
+  }
+
+  @pragma("vm:non-nullable-result-type")
+  @pragma("vm:prefer-inline")
+  _TypedList get _typedData native "TypedDataView_typedData";
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  @pragma("vm:prefer-inline")
+  int get offsetInBytes native "TypedDataView_offsetInBytes";
+
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  @pragma("vm:prefer-inline")
+  int get length native "TypedDataView_length";
+}
+
+@pragma("vm:prefer-inline")
+int _byteSwap16(int value) {
+  return ((value & 0xFF00) >> 8) | ((value & 0x00FF) << 8);
+}
+
+@pragma("vm:prefer-inline")
+int _byteSwap32(int value) {
+  value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
+  value = ((value & 0xFFFF0000) >> 16) | ((value & 0x0000FFFF) << 16);
+  return value;
+}
+
+@pragma("vm:prefer-inline")
+int _byteSwap64(int value) {
+  return (_byteSwap32(value) << 32) | _byteSwap32(value >> 32);
+}
+
+final _convU32 = new Uint32List(2);
+final _convU64 = new Uint64List.view(_convU32.buffer);
+final _convF32 = new Float32List.view(_convU32.buffer);
+final _convF64 = new Float64List.view(_convU32.buffer);
+
+// Top level utility methods.
+@pragma("vm:prefer-inline")
+int _toInt(int value, int mask) {
+  value &= mask;
+  if (value > (mask >> 1)) value -= mask + 1;
+  return value;
+}
+
+@pragma("vm:prefer-inline")
+int _toInt8(int value) {
+  return _toInt(value, 0xFF);
+}
+
+@pragma("vm:prefer-inline")
+int _toUint8(int value) {
+  return value & 0xFF;
+}
+
+@pragma("vm:exact-result-type", "dart:core#_Smi")
+int _toClampedUint8(int value) {
+  if (value < 0) return 0;
+  if (value > 0xFF) return 0xFF;
+  return value;
+}
+
+@pragma("vm:prefer-inline")
+int _toInt16(int value) {
+  return _toInt(value, 0xFFFF);
+}
+
+@pragma("vm:prefer-inline")
+int _toUint16(int value) {
+  return value & 0xFFFF;
+}
+
+@pragma("vm:prefer-inline")
+int _toInt32(int value) {
+  return _toInt(value, 0xFFFFFFFF);
+}
+
+@pragma("vm:prefer-inline")
+int _toUint32(int value) {
+  return value & 0xFFFFFFFF;
+}
+
+// In addition to explicitly checking the range, this method implicitly ensures
+// that all arguments are non-null (a no such method error gets thrown
+// otherwise).
+void _rangeCheck(int listLength, int start, int length) {
+  if (length < 0) {
+    throw new RangeError.value(length);
+  }
+  if (start < 0) {
+    throw new RangeError.value(start);
+  }
+  if (start + length > listLength) {
+    throw new RangeError.value(start + length);
+  }
+}
+
+void _offsetAlignmentCheck(int offset, int alignment) {
+  if ((offset % alignment) != 0) {
+    throw new RangeError('Offset ($offset) must be a multiple of '
+        'BYTES_PER_ELEMENT ($alignment)');
+  }
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/uri_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/uri_patch.dart
new file mode 100644
index 0000000..57fe914
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/uri_patch.dart
@@ -0,0 +1,82 @@
+// 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 "core_patch.dart";
+
+typedef Uri _UriBaseClosure();
+
+Uri _unsupportedUriBase() {
+  throw new UnsupportedError("'Uri.base' is not supported");
+}
+
+// _uriBaseClosure can be overwritten by the embedder to supply a different
+// value for Uri.base.
+@pragma("vm:entry-point")
+_UriBaseClosure _uriBaseClosure = _unsupportedUriBase;
+
+@patch
+class Uri {
+  @patch
+  static Uri get base => _uriBaseClosure();
+}
+
+/// VM implementation of Uri.
+@patch
+class _Uri {
+  static final bool _isWindowsCached = _isWindowsPlatform;
+
+  static bool get _isWindowsPlatform native "Uri_isWindowsPlatform";
+
+  @patch
+  static bool get _isWindows => _isWindowsCached;
+
+  @patch
+  static String _uriEncode(List<int> canonicalTable, String text,
+      Encoding encoding, bool spaceToPlus) {
+    // First check if the text will be changed by encoding.
+    int i = 0;
+    if (identical(encoding, utf8) ||
+        identical(encoding, latin1) ||
+        identical(encoding, ascii)) {
+      // Encoding is compatible with the original string.
+      // Find first character that needs encoding.
+      for (; i < text.length; i++) {
+        var char = text.codeUnitAt(i);
+        if (char >= 128 ||
+            canonicalTable[char >> 4] & (1 << (char & 0x0f)) == 0) {
+          break;
+        }
+      }
+    }
+    if (i == text.length) return text;
+
+    // Encode the string into bytes then generate an ASCII only string
+    // by percent encoding selected bytes.
+    StringBuffer result = new StringBuffer();
+    for (int j = 0; j < i; j++) {
+      result.writeCharCode(text.codeUnitAt(j));
+    }
+
+    // TODO(lrn): Is there a way to only encode from index i and forwards.
+    var bytes = encoding.encode(text);
+    for (; i < bytes.length; i++) {
+      int byte = bytes[i];
+      if (byte < 128 &&
+          ((canonicalTable[byte >> 4] & (1 << (byte & 0x0f))) != 0)) {
+        result.writeCharCode(byte);
+      } else if (spaceToPlus && byte == _SPACE) {
+        result.writeCharCode(_PLUS);
+      } else {
+        const String hexDigits = '0123456789ABCDEF';
+        result
+          ..writeCharCode(_PERCENT)
+          ..writeCharCode(hexDigits.codeUnitAt(byte >> 4))
+          ..writeCharCode(hexDigits.codeUnitAt(byte & 0x0f));
+      }
+    }
+    return result.toString();
+  }
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/wasm_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/wasm_patch.dart
new file mode 100644
index 0000000..fc33afa
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/wasm_patch.dart
@@ -0,0 +1,151 @@
+// 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
+
+import 'dart:_internal' show patch;
+import "dart:nativewrappers" show NativeFieldWrapperClass1;
+import 'dart:typed_data';
+
+@patch
+@pragma("vm:entry-point")
+class Int32 {}
+
+@patch
+@pragma("vm:entry-point")
+class Int64 {}
+
+@patch
+@pragma("vm:entry-point")
+class Float {}
+
+@patch
+@pragma("vm:entry-point")
+class Double {}
+
+@patch
+@pragma("vm:entry-point")
+class Void {}
+
+@patch
+class WasmModule {
+  @patch
+  factory WasmModule(Uint8List data) {
+    return _NativeWasmModule(data);
+  }
+}
+
+@patch
+class WasmMemory {
+  @patch
+  factory WasmMemory(int initialPages, [int maxPages]) {
+    return _NativeWasmMemory(initialPages, maxPages);
+  }
+}
+
+@patch
+class WasmImports {
+  @patch
+  factory WasmImports(String moduleName) {
+    return _NativeWasmImports(moduleName);
+  }
+}
+
+class _NativeWasmModule extends NativeFieldWrapperClass1 implements WasmModule {
+  _NativeWasmModule(Uint8List data) {
+    _init(data);
+  }
+
+  WasmInstance instantiate(covariant _NativeWasmImports imports) {
+    return _NativeWasmInstance(this, imports);
+  }
+
+  void _init(Uint8List data) native 'Wasm_initModule';
+}
+
+class _NativeWasmImports extends NativeFieldWrapperClass1
+    implements WasmImports {
+  List<WasmMemory> _memories;
+
+  _NativeWasmImports(String moduleName) : _memories = [] {
+    _init(moduleName);
+  }
+
+  void addMemory(String name, WasmMemory memory) {
+    _memories.add(memory);
+    _addMemory(name, memory);
+  }
+
+  void addGlobal<T>(String name, num value, bool mutable) {
+    _addGlobal(name, value, T, mutable);
+  }
+
+  void _init(String moduleName) native 'Wasm_initImports';
+  void _addMemory(String name, WasmMemory memory) native 'Wasm_addMemoryImport';
+  void _addGlobal(String name, num value, Type type, bool mutable)
+      native 'Wasm_addGlobalImport';
+}
+
+class _NativeWasmMemory extends NativeFieldWrapperClass1 implements WasmMemory {
+  int _pages;
+  Uint8List _buffer;
+
+  _NativeWasmMemory(int initialPages, int maxPages) : _pages = initialPages {
+    _buffer = _init(initialPages, maxPages);
+  }
+
+  int get lengthInPages => _pages;
+  int get lengthInBytes => _buffer.lengthInBytes;
+  int operator [](int index) => _buffer[index];
+  void operator []=(int index, int value) {
+    _buffer[index] = value;
+  }
+
+  int grow(int deltaPages) {
+    int oldPages = _pages;
+    _buffer = _grow(deltaPages);
+    _pages += deltaPages;
+    return oldPages;
+  }
+
+  Uint8List _init(int initialPages, int maxPages) native 'Wasm_initMemory';
+  Uint8List _grow(int deltaPages) native 'Wasm_growMemory';
+}
+
+class _NativeWasmInstance extends NativeFieldWrapperClass1
+    implements WasmInstance {
+  _NativeWasmModule _module;
+  _NativeWasmImports _imports;
+
+  _NativeWasmInstance(_NativeWasmModule module, _NativeWasmImports imports)
+      : _module = module,
+        _imports = imports {
+    _init(module, imports);
+  }
+
+  WasmFunction<T> lookupFunction<T extends Function>(String name) {
+    return _NativeWasmFunction<T>(this, name);
+  }
+
+  void _init(_NativeWasmModule module, _NativeWasmImports imports)
+      native 'Wasm_initInstance';
+}
+
+class _NativeWasmFunction<T extends Function> extends NativeFieldWrapperClass1
+    implements WasmFunction<T> {
+  _NativeWasmInstance _inst;
+
+  _NativeWasmFunction(_NativeWasmInstance inst, String name) : _inst = inst {
+    _init(inst, name, T);
+  }
+
+  num call(List<num> args) {
+    var arg_copy = List<num>.from(args, growable: false);
+    return _call(arg_copy);
+  }
+
+  void _init(_NativeWasmInstance inst, String name, Type fnType)
+      native 'Wasm_initFunction';
+  num _call(List<num> args) native 'Wasm_callFunction';
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/weak_property.dart b/sdk_nnbd/lib/_internal/vm/lib/weak_property.dart
new file mode 100644
index 0000000..9f689d1
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/vm/lib/weak_property.dart
@@ -0,0 +1,22 @@
+// 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.
+
+// @dart = 2.5
+
+// part of "core_patch.dart";
+
+@pragma("vm:entry-point")
+class _WeakProperty {
+  factory _WeakProperty(key, value) => _new(key, value);
+
+  get key => _getKey();
+  get value => _getValue();
+  set value(value) => _setValue(value);
+
+  static _WeakProperty _new(key, value) native "WeakProperty_new";
+
+  _getKey() native "WeakProperty_getKey";
+  _getValue() native "WeakProperty_getValue";
+  _setValue(value) native "WeakProperty_setValue";
+}
diff --git a/sdk_nnbd/lib/async/async.dart b/sdk_nnbd/lib/async/async.dart
index b3a5dbd..b4bec24 100644
--- a/sdk_nnbd/lib/async/async.dart
+++ b/sdk_nnbd/lib/async/async.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 /**
  * Support for asynchronous programming,
  * with classes such as Future and Stream.
diff --git a/sdk_nnbd/lib/async/async_error.dart b/sdk_nnbd/lib/async/async_error.dart
index 1520c54..5edac63 100644
--- a/sdk_nnbd/lib/async/async_error.dart
+++ b/sdk_nnbd/lib/async/async_error.dart
@@ -2,6 +2,8 @@
 // for details. All 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.async;
 
 _invokeErrorHandler(
diff --git a/sdk_nnbd/lib/async/broadcast_stream_controller.dart b/sdk_nnbd/lib/async/broadcast_stream_controller.dart
index 32e4582..c5358f2 100644
--- a/sdk_nnbd/lib/async/broadcast_stream_controller.dart
+++ b/sdk_nnbd/lib/async/broadcast_stream_controller.dart
@@ -2,6 +2,8 @@
 // for details. All 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.async;
 
 class _BroadcastStream<T> extends _ControllerStream<T> {
diff --git a/sdk_nnbd/lib/async/deferred_load.dart b/sdk_nnbd/lib/async/deferred_load.dart
index f83d4b8..1e2be92 100644
--- a/sdk_nnbd/lib/async/deferred_load.dart
+++ b/sdk_nnbd/lib/async/deferred_load.dart
@@ -2,6 +2,8 @@
 // for details. All 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.async;
 
 /**
diff --git a/sdk_nnbd/lib/async/future.dart b/sdk_nnbd/lib/async/future.dart
index b9d22c1..2f9c24d 100644
--- a/sdk_nnbd/lib/async/future.dart
+++ b/sdk_nnbd/lib/async/future.dart
@@ -2,6 +2,8 @@
 // for details. All 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.async;
 
 /// A type representing values that are either `Future<T>` or `T`.
diff --git a/sdk_nnbd/lib/async/future_impl.dart b/sdk_nnbd/lib/async/future_impl.dart
index 1ec0791..c9685ff 100644
--- a/sdk_nnbd/lib/async/future_impl.dart
+++ b/sdk_nnbd/lib/async/future_impl.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.async;
 
 /** The onValue and onError handlers return either a value or a future */
diff --git a/sdk_nnbd/lib/async/schedule_microtask.dart b/sdk_nnbd/lib/async/schedule_microtask.dart
index 801490a..41b9d31 100644
--- a/sdk_nnbd/lib/async/schedule_microtask.dart
+++ b/sdk_nnbd/lib/async/schedule_microtask.dart
@@ -2,6 +2,8 @@
 // for details. All 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.async;
 
 typedef void _AsyncCallback();
diff --git a/sdk_nnbd/lib/async/stream.dart b/sdk_nnbd/lib/async/stream.dart
index 95a8b97..ba3dad6 100644
--- a/sdk_nnbd/lib/async/stream.dart
+++ b/sdk_nnbd/lib/async/stream.dart
@@ -2,6 +2,8 @@
 // for details. All 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.async;
 
 // -------------------------------------------------------------------
diff --git a/sdk_nnbd/lib/async/stream_controller.dart b/sdk_nnbd/lib/async/stream_controller.dart
index 34c6adf..f8f2d6d 100644
--- a/sdk_nnbd/lib/async/stream_controller.dart
+++ b/sdk_nnbd/lib/async/stream_controller.dart
@@ -2,6 +2,8 @@
 // for details. All 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.async;
 
 // -------------------------------------------------------------------
diff --git a/sdk_nnbd/lib/async/stream_impl.dart b/sdk_nnbd/lib/async/stream_impl.dart
index 14c84a5..fac736c 100644
--- a/sdk_nnbd/lib/async/stream_impl.dart
+++ b/sdk_nnbd/lib/async/stream_impl.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.async;
 
 /** Abstract and private interface for a place to put events. */
diff --git a/sdk_nnbd/lib/async/stream_pipe.dart b/sdk_nnbd/lib/async/stream_pipe.dart
index e526179..1549ad5 100644
--- a/sdk_nnbd/lib/async/stream_pipe.dart
+++ b/sdk_nnbd/lib/async/stream_pipe.dart
@@ -2,6 +2,8 @@
 // for details. All 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.async;
 
 /** Runs user code and takes actions depending on success or failure. */
diff --git a/sdk_nnbd/lib/async/stream_transformers.dart b/sdk_nnbd/lib/async/stream_transformers.dart
index 9ec13bd..5c788fe 100644
--- a/sdk_nnbd/lib/async/stream_transformers.dart
+++ b/sdk_nnbd/lib/async/stream_transformers.dart
@@ -2,6 +2,8 @@
 // for details. All 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.async;
 
 /**
diff --git a/sdk_nnbd/lib/async/timer.dart b/sdk_nnbd/lib/async/timer.dart
index aa2f088..e3f7edb 100644
--- a/sdk_nnbd/lib/async/timer.dart
+++ b/sdk_nnbd/lib/async/timer.dart
@@ -2,6 +2,8 @@
 // for details. All 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.async;
 
 /**
diff --git a/sdk_nnbd/lib/async/zone.dart b/sdk_nnbd/lib/async/zone.dart
index 911ecff..6a2d015 100644
--- a/sdk_nnbd/lib/async/zone.dart
+++ b/sdk_nnbd/lib/async/zone.dart
@@ -2,6 +2,8 @@
 // for details. All 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.async;
 
 typedef R ZoneCallback<R>();
diff --git a/sdk_nnbd/lib/cli/cli.dart b/sdk_nnbd/lib/cli/cli.dart
index 9c19c3a..4748181 100644
--- a/sdk_nnbd/lib/cli/cli.dart
+++ b/sdk_nnbd/lib/cli/cli.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 /// {@category VM}
 library dart.cli;
 
diff --git a/sdk_nnbd/lib/cli/wait_for.dart b/sdk_nnbd/lib/cli/wait_for.dart
index 1886ff1..d4dd71e 100644
--- a/sdk_nnbd/lib/cli/wait_for.dart
+++ b/sdk_nnbd/lib/cli/wait_for.dart
@@ -2,6 +2,8 @@
 // for details. All 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.cli;
 
 /**
diff --git a/sdk_nnbd/lib/collection/collection.dart b/sdk_nnbd/lib/collection/collection.dart
index b050a48..644bcff 100644
--- a/sdk_nnbd/lib/collection/collection.dart
+++ b/sdk_nnbd/lib/collection/collection.dart
@@ -2,6 +2,8 @@
 // for details. All 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 9b43996..f836d8e 100644
--- a/sdk_nnbd/lib/collection/collections.dart
+++ b/sdk_nnbd/lib/collection/collections.dart
@@ -2,6 +2,8 @@
 // for details. All 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 525f43a..18ea1b6 100644
--- a/sdk_nnbd/lib/collection/hash_map.dart
+++ b/sdk_nnbd/lib/collection/hash_map.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.collection;
 
 /// Default function for equality comparison in customized HashMaps
diff --git a/sdk_nnbd/lib/collection/hash_set.dart b/sdk_nnbd/lib/collection/hash_set.dart
index 3fd00fe..61f1f6c 100644
--- a/sdk_nnbd/lib/collection/hash_set.dart
+++ b/sdk_nnbd/lib/collection/hash_set.dart
@@ -2,6 +2,8 @@
 // for details. All 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.
diff --git a/sdk_nnbd/lib/collection/iterable.dart b/sdk_nnbd/lib/collection/iterable.dart
index 14e7226..8ac38b2 100644
--- a/sdk_nnbd/lib/collection/iterable.dart
+++ b/sdk_nnbd/lib/collection/iterable.dart
@@ -2,6 +2,8 @@
 // for details. All 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`.
diff --git a/sdk_nnbd/lib/collection/iterator.dart b/sdk_nnbd/lib/collection/iterator.dart
index 671f0ee..e7e0c3b 100644
--- a/sdk_nnbd/lib/collection/iterator.dart
+++ b/sdk_nnbd/lib/collection/iterator.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.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 e3a650d..de94009 100644
--- a/sdk_nnbd/lib/collection/linked_hash_map.dart
+++ b/sdk_nnbd/lib/collection/linked_hash_map.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.collection;
 
 /// A hash-table based implementation of [Map].
diff --git a/sdk_nnbd/lib/collection/linked_hash_set.dart b/sdk_nnbd/lib/collection/linked_hash_set.dart
index a058b5e..195b5fb 100644
--- a/sdk_nnbd/lib/collection/linked_hash_set.dart
+++ b/sdk_nnbd/lib/collection/linked_hash_set.dart
@@ -2,6 +2,8 @@
 // for details. All 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.
diff --git a/sdk_nnbd/lib/collection/linked_list.dart b/sdk_nnbd/lib/collection/linked_list.dart
index 91461cb..9ef7a56 100644
--- a/sdk_nnbd/lib/collection/linked_list.dart
+++ b/sdk_nnbd/lib/collection/linked_list.dart
@@ -2,6 +2,8 @@
 // for details. All 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].
diff --git a/sdk_nnbd/lib/collection/list.dart b/sdk_nnbd/lib/collection/list.dart
index 1d83aa4..911820b 100644
--- a/sdk_nnbd/lib/collection/list.dart
+++ b/sdk_nnbd/lib/collection/list.dart
@@ -2,6 +2,8 @@
 // for details. All 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.
diff --git a/sdk_nnbd/lib/collection/maps.dart b/sdk_nnbd/lib/collection/maps.dart
index 8159342..7fb2551 100644
--- a/sdk_nnbd/lib/collection/maps.dart
+++ b/sdk_nnbd/lib/collection/maps.dart
@@ -2,6 +2,8 @@
 // for details. All 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].
diff --git a/sdk_nnbd/lib/collection/queue.dart b/sdk_nnbd/lib/collection/queue.dart
index 62994b9..77b27b1 100644
--- a/sdk_nnbd/lib/collection/queue.dart
+++ b/sdk_nnbd/lib/collection/queue.dart
@@ -2,6 +2,8 @@
 // for details. All 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
diff --git a/sdk_nnbd/lib/collection/set.dart b/sdk_nnbd/lib/collection/set.dart
index 7508b23..b6b9efc 100644
--- a/sdk_nnbd/lib/collection/set.dart
+++ b/sdk_nnbd/lib/collection/set.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 
diff --git a/sdk_nnbd/lib/collection/splay_tree.dart b/sdk_nnbd/lib/collection/splay_tree.dart
index 5f71934..ef3e51f 100644
--- a/sdk_nnbd/lib/collection/splay_tree.dart
+++ b/sdk_nnbd/lib/collection/splay_tree.dart
@@ -2,6 +2,8 @@
 // for details. All 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);
diff --git a/sdk_nnbd/lib/convert/ascii.dart b/sdk_nnbd/lib/convert/ascii.dart
index 35105ac..307ac08 100644
--- a/sdk_nnbd/lib/convert/ascii.dart
+++ b/sdk_nnbd/lib/convert/ascii.dart
@@ -2,6 +2,8 @@
 // for details. All 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].
diff --git a/sdk_nnbd/lib/convert/base64.dart b/sdk_nnbd/lib/convert/base64.dart
index ce522be..4187658 100644
--- a/sdk_nnbd/lib/convert/base64.dart
+++ b/sdk_nnbd/lib/convert/base64.dart
@@ -2,6 +2,8 @@
 // for details. All 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.
diff --git a/sdk_nnbd/lib/convert/byte_conversion.dart b/sdk_nnbd/lib/convert/byte_conversion.dart
index 3d52d78..9e66ecd 100644
--- a/sdk_nnbd/lib/convert/byte_conversion.dart
+++ b/sdk_nnbd/lib/convert/byte_conversion.dart
@@ -2,6 +2,8 @@
 // for details. All 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 e946f97..d2f1a7c 100644
--- a/sdk_nnbd/lib/convert/chunked_conversion.dart
+++ b/sdk_nnbd/lib/convert/chunked_conversion.dart
@@ -2,6 +2,8 @@
 // for details. All 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
diff --git a/sdk_nnbd/lib/convert/codec.dart b/sdk_nnbd/lib/convert/codec.dart
index 38e4a3c..7c9fb07 100644
--- a/sdk_nnbd/lib/convert/codec.dart
+++ b/sdk_nnbd/lib/convert/codec.dart
@@ -2,6 +2,8 @@
 // for details. All 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 6173782..727a8c8 100644
--- a/sdk_nnbd/lib/convert/convert.dart
+++ b/sdk_nnbd/lib/convert/convert.dart
@@ -2,6 +2,8 @@
 // for details. All 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 2167933..0205771 100644
--- a/sdk_nnbd/lib/convert/converter.dart
+++ b/sdk_nnbd/lib/convert/converter.dart
@@ -2,6 +2,8 @@
 // for details. All 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 7ce8ec3..d6d36ee 100644
--- a/sdk_nnbd/lib/convert/encoding.dart
+++ b/sdk_nnbd/lib/convert/encoding.dart
@@ -2,6 +2,8 @@
 // for details. All 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.
diff --git a/sdk_nnbd/lib/convert/html_escape.dart b/sdk_nnbd/lib/convert/html_escape.dart
index a0a7119..98f24df 100644
--- a/sdk_nnbd/lib/convert/html_escape.dart
+++ b/sdk_nnbd/lib/convert/html_escape.dart
@@ -2,6 +2,8 @@
 // for details. All 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.
diff --git a/sdk_nnbd/lib/convert/json.dart b/sdk_nnbd/lib/convert/json.dart
index 5746e52..6ac392a 100644
--- a/sdk_nnbd/lib/convert/json.dart
+++ b/sdk_nnbd/lib/convert/json.dart
@@ -2,6 +2,8 @@
 // for details. All 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.
diff --git a/sdk_nnbd/lib/convert/latin1.dart b/sdk_nnbd/lib/convert/latin1.dart
index c22010c..305017f 100644
--- a/sdk_nnbd/lib/convert/latin1.dart
+++ b/sdk_nnbd/lib/convert/latin1.dart
@@ -2,6 +2,8 @@
 // for details. All 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].
diff --git a/sdk_nnbd/lib/convert/line_splitter.dart b/sdk_nnbd/lib/convert/line_splitter.dart
index 71be2c0..6980e88 100644
--- a/sdk_nnbd/lib/convert/line_splitter.dart
+++ b/sdk_nnbd/lib/convert/line_splitter.dart
@@ -2,6 +2,8 @@
 // for details. All 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.
diff --git a/sdk_nnbd/lib/convert/string_conversion.dart b/sdk_nnbd/lib/convert/string_conversion.dart
index 81e5621..94d129c 100644
--- a/sdk_nnbd/lib/convert/string_conversion.dart
+++ b/sdk_nnbd/lib/convert/string_conversion.dart
@@ -2,6 +2,8 @@
 // for details. All 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
diff --git a/sdk_nnbd/lib/convert/utf.dart b/sdk_nnbd/lib/convert/utf.dart
index 39eb135..692a01c 100644
--- a/sdk_nnbd/lib/convert/utf.dart
+++ b/sdk_nnbd/lib/convert/utf.dart
@@ -2,6 +2,8 @@
 // for details. All 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` (�).
diff --git a/sdk_nnbd/lib/core/annotations.dart b/sdk_nnbd/lib/core/annotations.dart
index 2d30f1c..4592eb0 100644
--- a/sdk_nnbd/lib/core/annotations.dart
+++ b/sdk_nnbd/lib/core/annotations.dart
@@ -2,6 +2,8 @@
 // for details. All 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/bigint.dart b/sdk_nnbd/lib/core/bigint.dart
index b495a9e..e6f3ba0 100644
--- a/sdk_nnbd/lib/core/bigint.dart
+++ b/sdk_nnbd/lib/core/bigint.dart
@@ -2,6 +2,8 @@
 // for details. All 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/bool.dart b/sdk_nnbd/lib/core/bool.dart
index 5ed1065..692186f 100644
--- a/sdk_nnbd/lib/core/bool.dart
+++ b/sdk_nnbd/lib/core/bool.dart
@@ -2,6 +2,8 @@
 // for details. All 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/comparable.dart b/sdk_nnbd/lib/core/comparable.dart
index 835aa34..4416dc0 100644
--- a/sdk_nnbd/lib/core/comparable.dart
+++ b/sdk_nnbd/lib/core/comparable.dart
@@ -2,6 +2,8 @@
 // for details. All 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 9ab8ed4..d9137cd 100644
--- a/sdk_nnbd/lib/core/core.dart
+++ b/sdk_nnbd/lib/core/core.dart
@@ -2,6 +2,8 @@
 // for details. All 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,
diff --git a/sdk_nnbd/lib/core/date_time.dart b/sdk_nnbd/lib/core/date_time.dart
index dd242de..1dd01bb 100644
--- a/sdk_nnbd/lib/core/date_time.dart
+++ b/sdk_nnbd/lib/core/date_time.dart
@@ -2,6 +2,8 @@
 // for details. All 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/double.dart b/sdk_nnbd/lib/core/double.dart
index 61191ec..f8d109c 100644
--- a/sdk_nnbd/lib/core/double.dart
+++ b/sdk_nnbd/lib/core/double.dart
@@ -2,6 +2,8 @@
 // for details. All 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
diff --git a/sdk_nnbd/lib/core/duration.dart b/sdk_nnbd/lib/core/duration.dart
index 914f05a..f68609f 100644
--- a/sdk_nnbd/lib/core/duration.dart
+++ b/sdk_nnbd/lib/core/duration.dart
@@ -2,6 +2,8 @@
 // for details. All 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/errors.dart b/sdk_nnbd/lib/core/errors.dart
index 53f3d35..b2454f8 100644
--- a/sdk_nnbd/lib/core/errors.dart
+++ b/sdk_nnbd/lib/core/errors.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.core;
 
 /**
diff --git a/sdk_nnbd/lib/core/exceptions.dart b/sdk_nnbd/lib/core/exceptions.dart
index 2e137e5..4ac5ace 100644
--- a/sdk_nnbd/lib/core/exceptions.dart
+++ b/sdk_nnbd/lib/core/exceptions.dart
@@ -2,6 +2,8 @@
 // for details. All 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.
diff --git a/sdk_nnbd/lib/core/expando.dart b/sdk_nnbd/lib/core/expando.dart
index 92cf90c..132d38a 100644
--- a/sdk_nnbd/lib/core/expando.dart
+++ b/sdk_nnbd/lib/core/expando.dart
@@ -2,6 +2,8 @@
 // for details. All 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/function.dart b/sdk_nnbd/lib/core/function.dart
index 7ff40e9..6c0462b 100644
--- a/sdk_nnbd/lib/core/function.dart
+++ b/sdk_nnbd/lib/core/function.dart
@@ -2,6 +2,8 @@
 // for details. All 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/identical.dart b/sdk_nnbd/lib/core/identical.dart
index 68da9f3..8789642 100644
--- a/sdk_nnbd/lib/core/identical.dart
+++ b/sdk_nnbd/lib/core/identical.dart
@@ -2,6 +2,8 @@
 // for details. All 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/int.dart b/sdk_nnbd/lib/core/int.dart
index bc493fb..a55641c 100644
--- a/sdk_nnbd/lib/core/int.dart
+++ b/sdk_nnbd/lib/core/int.dart
@@ -2,6 +2,8 @@
 // for details. All 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/invocation.dart b/sdk_nnbd/lib/core/invocation.dart
index e9ea57e..6644a84 100644
--- a/sdk_nnbd/lib/core/invocation.dart
+++ b/sdk_nnbd/lib/core/invocation.dart
@@ -2,6 +2,8 @@
 // for details. All 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/iterable.dart b/sdk_nnbd/lib/core/iterable.dart
index 0744937..32225b0 100644
--- a/sdk_nnbd/lib/core/iterable.dart
+++ b/sdk_nnbd/lib/core/iterable.dart
@@ -2,6 +2,8 @@
 // for details. All 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/iterator.dart b/sdk_nnbd/lib/core/iterator.dart
index cd0ad32..d69e937 100644
--- a/sdk_nnbd/lib/core/iterator.dart
+++ b/sdk_nnbd/lib/core/iterator.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.core;
 
 /**
diff --git a/sdk_nnbd/lib/core/list.dart b/sdk_nnbd/lib/core/list.dart
index 27e1653..b096bfa 100644
--- a/sdk_nnbd/lib/core/list.dart
+++ b/sdk_nnbd/lib/core/list.dart
@@ -2,6 +2,8 @@
 // for details. All 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/map.dart b/sdk_nnbd/lib/core/map.dart
index f914fe1..fa1573a 100644
--- a/sdk_nnbd/lib/core/map.dart
+++ b/sdk_nnbd/lib/core/map.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.core;
 
 /**
diff --git a/sdk_nnbd/lib/core/null.dart b/sdk_nnbd/lib/core/null.dart
index af7d86d..0e8dec5 100644
--- a/sdk_nnbd/lib/core/null.dart
+++ b/sdk_nnbd/lib/core/null.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.core;
 
 /**
diff --git a/sdk_nnbd/lib/core/num.dart b/sdk_nnbd/lib/core/num.dart
index e04112c..e7afd77 100644
--- a/sdk_nnbd/lib/core/num.dart
+++ b/sdk_nnbd/lib/core/num.dart
@@ -2,6 +2,8 @@
 // for details. All 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/object.dart b/sdk_nnbd/lib/core/object.dart
index 505efdf..6490430 100644
--- a/sdk_nnbd/lib/core/object.dart
+++ b/sdk_nnbd/lib/core/object.dart
@@ -2,6 +2,8 @@
 // for details. All 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/pattern.dart b/sdk_nnbd/lib/core/pattern.dart
index 6749340..42607e1 100644
--- a/sdk_nnbd/lib/core/pattern.dart
+++ b/sdk_nnbd/lib/core/pattern.dart
@@ -2,6 +2,8 @@
 // for details. All 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/print.dart b/sdk_nnbd/lib/core/print.dart
index 42c7d1c..6b33db5 100644
--- a/sdk_nnbd/lib/core/print.dart
+++ b/sdk_nnbd/lib/core/print.dart
@@ -2,6 +2,8 @@
 // for details. All 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.
diff --git a/sdk_nnbd/lib/core/regexp.dart b/sdk_nnbd/lib/core/regexp.dart
index b3046cc..4d1228c 100644
--- a/sdk_nnbd/lib/core/regexp.dart
+++ b/sdk_nnbd/lib/core/regexp.dart
@@ -2,6 +2,8 @@
 // for details. All 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/set.dart b/sdk_nnbd/lib/core/set.dart
index e57d974..d0be04c 100644
--- a/sdk_nnbd/lib/core/set.dart
+++ b/sdk_nnbd/lib/core/set.dart
@@ -2,6 +2,8 @@
 // for details. All 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/sink.dart b/sdk_nnbd/lib/core/sink.dart
index c79214b..ed921b1 100644
--- a/sdk_nnbd/lib/core/sink.dart
+++ b/sdk_nnbd/lib/core/sink.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.core;
 
 /**
diff --git a/sdk_nnbd/lib/core/stacktrace.dart b/sdk_nnbd/lib/core/stacktrace.dart
index 2eb1493..434be96 100644
--- a/sdk_nnbd/lib/core/stacktrace.dart
+++ b/sdk_nnbd/lib/core/stacktrace.dart
@@ -2,6 +2,8 @@
 // for details. All 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 45d71ca..0db02c9 100644
--- a/sdk_nnbd/lib/core/stopwatch.dart
+++ b/sdk_nnbd/lib/core/stopwatch.dart
@@ -2,6 +2,8 @@
 // for details. All 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/string.dart b/sdk_nnbd/lib/core/string.dart
index c611bd5..7559f9c 100644
--- a/sdk_nnbd/lib/core/string.dart
+++ b/sdk_nnbd/lib/core/string.dart
@@ -2,6 +2,8 @@
 // for details. All 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/string_buffer.dart b/sdk_nnbd/lib/core/string_buffer.dart
index 8fe17f5..417676a 100644
--- a/sdk_nnbd/lib/core/string_buffer.dart
+++ b/sdk_nnbd/lib/core/string_buffer.dart
@@ -2,6 +2,8 @@
 // for details. All 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/string_sink.dart b/sdk_nnbd/lib/core/string_sink.dart
index e7d950c..8c19b9b 100644
--- a/sdk_nnbd/lib/core/string_sink.dart
+++ b/sdk_nnbd/lib/core/string_sink.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.core;
 
 abstract class StringSink {
diff --git a/sdk_nnbd/lib/core/symbol.dart b/sdk_nnbd/lib/core/symbol.dart
index a46ec97..2904b9f 100644
--- a/sdk_nnbd/lib/core/symbol.dart
+++ b/sdk_nnbd/lib/core/symbol.dart
@@ -2,6 +2,8 @@
 // for details. All 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].
diff --git a/sdk_nnbd/lib/core/type.dart b/sdk_nnbd/lib/core/type.dart
index d2e107b..8657cd4 100644
--- a/sdk_nnbd/lib/core/type.dart
+++ b/sdk_nnbd/lib/core/type.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.core;
 
 /**
diff --git a/sdk_nnbd/lib/core/uri.dart b/sdk_nnbd/lib/core/uri.dart
index 2ca94a1..478e9d7 100644
--- a/sdk_nnbd/lib/core/uri.dart
+++ b/sdk_nnbd/lib/core/uri.dart
@@ -2,6 +2,8 @@
 // for details. All 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.
diff --git a/sdk_nnbd/lib/developer/developer.dart b/sdk_nnbd/lib/developer/developer.dart
index c446fdf..732e1d9 100644
--- a/sdk_nnbd/lib/developer/developer.dart
+++ b/sdk_nnbd/lib/developer/developer.dart
@@ -2,6 +2,8 @@
 // for details. All 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
diff --git a/sdk_nnbd/lib/developer/extension.dart b/sdk_nnbd/lib/developer/extension.dart
index 3cc4ede..d292857 100644
--- a/sdk_nnbd/lib/developer/extension.dart
+++ b/sdk_nnbd/lib/developer/extension.dart
@@ -2,6 +2,8 @@
 // for details. All 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.
diff --git a/sdk_nnbd/lib/developer/profiler.dart b/sdk_nnbd/lib/developer/profiler.dart
index 05a9211..f08df89 100644
--- a/sdk_nnbd/lib/developer/profiler.dart
+++ b/sdk_nnbd/lib/developer/profiler.dart
@@ -2,6 +2,8 @@
 // for details. All 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.
diff --git a/sdk_nnbd/lib/developer/service.dart b/sdk_nnbd/lib/developer/service.dart
index a4d92b9..2678da7 100644
--- a/sdk_nnbd/lib/developer/service.dart
+++ b/sdk_nnbd/lib/developer/service.dart
@@ -2,6 +2,8 @@
 // for details. All 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
diff --git a/sdk_nnbd/lib/developer/timeline.dart b/sdk_nnbd/lib/developer/timeline.dart
index 02f9c98..2e5f4ec 100644
--- a/sdk_nnbd/lib/developer/timeline.dart
+++ b/sdk_nnbd/lib/developer/timeline.dart
@@ -2,6 +2,8 @@
 // for details. All 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 =
diff --git a/sdk_nnbd/lib/ffi/annotations.dart b/sdk_nnbd/lib/ffi/annotations.dart
index d246b56..c4e9b7f 100644
--- a/sdk_nnbd/lib/ffi/annotations.dart
+++ b/sdk_nnbd/lib/ffi/annotations.dart
@@ -2,6 +2,8 @@
 // for details. All 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.ffi;
 
 class DartRepresentationOf {
diff --git a/sdk_nnbd/lib/ffi/dynamic_library.dart b/sdk_nnbd/lib/ffi/dynamic_library.dart
index ec68eeb..86cd117 100644
--- a/sdk_nnbd/lib/ffi/dynamic_library.dart
+++ b/sdk_nnbd/lib/ffi/dynamic_library.dart
@@ -2,6 +2,8 @@
 // for details. All 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.ffi;
 
 /// Represents a dynamically loaded C library.
diff --git a/sdk_nnbd/lib/ffi/ffi.dart b/sdk_nnbd/lib/ffi/ffi.dart
index a975a13..eb1bdcd 100644
--- a/sdk_nnbd/lib/ffi/ffi.dart
+++ b/sdk_nnbd/lib/ffi/ffi.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 /**
  * Foreign Function Interface for interoperability with the C programming language.
  *
diff --git a/sdk_nnbd/lib/ffi/native_type.dart b/sdk_nnbd/lib/ffi/native_type.dart
index aa30e63..1498ecc 100644
--- a/sdk_nnbd/lib/ffi/native_type.dart
+++ b/sdk_nnbd/lib/ffi/native_type.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.ffi;
 
 /// [NativeType]'s subtypes represent a native type in C.
diff --git a/sdk_nnbd/lib/ffi/struct.dart b/sdk_nnbd/lib/ffi/struct.dart
index 23124eb..33872f3 100644
--- a/sdk_nnbd/lib/ffi/struct.dart
+++ b/sdk_nnbd/lib/ffi/struct.dart
@@ -2,6 +2,8 @@
 // for details. All 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.ffi;
 
 /// This class is extended to define structs.
diff --git a/sdk_nnbd/lib/html/dart2js/html_dart2js.dart b/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
index 303ec9e..b5afe53 100644
--- a/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
+++ b/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
@@ -1,3 +1,5 @@
+// @dart = 2.5
+
 /**
  * HTML elements and other resources for web-based applications that need to
  * interact with the browser and the DOM (Document Object Model).
diff --git a/sdk_nnbd/lib/html/dartium/nativewrappers.dart b/sdk_nnbd/lib/html/dartium/nativewrappers.dart
index b6d2dc4..03fea72 100644
--- a/sdk_nnbd/lib/html/dartium/nativewrappers.dart
+++ b/sdk_nnbd/lib/html/dartium/nativewrappers.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 library nativewrappers;
 
 class NativeFieldWrapperClass1 {}
diff --git a/sdk_nnbd/lib/html/html_common/conversions.dart b/sdk_nnbd/lib/html/html_common/conversions.dart
index 4c31efb..ca118a9 100644
--- a/sdk_nnbd/lib/html/html_common/conversions.dart
+++ b/sdk_nnbd/lib/html/html_common/conversions.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 // Conversions for IDBKey.
 //
 // Per http://www.w3.org/TR/IndexedDB/#key-construct
diff --git a/sdk_nnbd/lib/html/html_common/conversions_dart2js.dart b/sdk_nnbd/lib/html/html_common/conversions_dart2js.dart
index 36153cf..08ce947 100644
--- a/sdk_nnbd/lib/html/html_common/conversions_dart2js.dart
+++ b/sdk_nnbd/lib/html/html_common/conversions_dart2js.dart
@@ -1,3 +1,5 @@
+// @dart = 2.5
+
 part of html_common;
 
 /// Converts a JavaScript object with properties into a Dart Map.
diff --git a/sdk_nnbd/lib/html/html_common/css_class_set.dart b/sdk_nnbd/lib/html/html_common/css_class_set.dart
index 2286057..bda757e 100644
--- a/sdk_nnbd/lib/html/html_common/css_class_set.dart
+++ b/sdk_nnbd/lib/html/html_common/css_class_set.dart
@@ -2,6 +2,8 @@
 // for details. All 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 html_common;
 
 abstract class CssClassSetImpl extends SetBase<String> implements CssClassSet {
diff --git a/sdk_nnbd/lib/html/html_common/device.dart b/sdk_nnbd/lib/html/html_common/device.dart
index 123a5db..1062bb6 100644
--- a/sdk_nnbd/lib/html/html_common/device.dart
+++ b/sdk_nnbd/lib/html/html_common/device.dart
@@ -2,6 +2,8 @@
 // for details. All 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 html_common;
 
 /**
diff --git a/sdk_nnbd/lib/html/html_common/filtered_element_list.dart b/sdk_nnbd/lib/html/html_common/filtered_element_list.dart
index fba6ad7..e3b0a3e 100644
--- a/sdk_nnbd/lib/html/html_common/filtered_element_list.dart
+++ b/sdk_nnbd/lib/html/html_common/filtered_element_list.dart
@@ -2,6 +2,8 @@
 // for details. All 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 html_common;
 
 /**
diff --git a/sdk_nnbd/lib/html/html_common/html_common.dart b/sdk_nnbd/lib/html/html_common/html_common.dart
index e689c9a..2dfec89 100644
--- a/sdk_nnbd/lib/html/html_common/html_common.dart
+++ b/sdk_nnbd/lib/html/html_common/html_common.dart
@@ -1,6 +1,8 @@
 // for details. All 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
+
 library html_common;
 
 import 'dart:async';
diff --git a/sdk_nnbd/lib/html/html_common/html_common_dart2js.dart b/sdk_nnbd/lib/html/html_common/html_common_dart2js.dart
index f162ad8..3a91281 100644
--- a/sdk_nnbd/lib/html/html_common/html_common_dart2js.dart
+++ b/sdk_nnbd/lib/html/html_common/html_common_dart2js.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 library html_common;
 
 import 'dart:async';
diff --git a/sdk_nnbd/lib/html/html_common/lists.dart b/sdk_nnbd/lib/html/html_common/lists.dart
index c7abc41..5f9d86c 100644
--- a/sdk_nnbd/lib/html/html_common/lists.dart
+++ b/sdk_nnbd/lib/html/html_common/lists.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of html_common;
 
 class Lists {
diff --git a/sdk_nnbd/lib/html/html_common/metadata.dart b/sdk_nnbd/lib/html/html_common/metadata.dart
index b5542dc..f21f495 100644
--- a/sdk_nnbd/lib/html/html_common/metadata.dart
+++ b/sdk_nnbd/lib/html/html_common/metadata.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 library metadata;
 
 /**
diff --git a/sdk_nnbd/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk_nnbd/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index b664b7d..baefa2a 100644
--- a/sdk_nnbd/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk_nnbd/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -1,3 +1,5 @@
+// @dart = 2.5
+
 /**
  * A client-side key-value store with support for indexes.
  *
diff --git a/sdk_nnbd/lib/internal/async_cast.dart b/sdk_nnbd/lib/internal/async_cast.dart
index e041ff3..9f4448d 100644
--- a/sdk_nnbd/lib/internal/async_cast.dart
+++ b/sdk_nnbd/lib/internal/async_cast.dart
@@ -2,6 +2,8 @@
 // for details. All 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._internal;
 
 // Casting wrappers for asynchronous classes.
diff --git a/sdk_nnbd/lib/internal/cast.dart b/sdk_nnbd/lib/internal/cast.dart
index b3620f5..ae20c66 100644
--- a/sdk_nnbd/lib/internal/cast.dart
+++ b/sdk_nnbd/lib/internal/cast.dart
@@ -2,6 +2,8 @@
 // for details. All 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._internal;
 
 // Casting wrappers for collection classes.
diff --git a/sdk_nnbd/lib/internal/internal.dart b/sdk_nnbd/lib/internal/internal.dart
index 11ee996..94fb13e 100644
--- a/sdk_nnbd/lib/internal/internal.dart
+++ b/sdk_nnbd/lib/internal/internal.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 library dart._internal;
 
 import 'dart:collection';
diff --git a/sdk_nnbd/lib/internal/iterable.dart b/sdk_nnbd/lib/internal/iterable.dart
index b3e8e4e..55cf780 100644
--- a/sdk_nnbd/lib/internal/iterable.dart
+++ b/sdk_nnbd/lib/internal/iterable.dart
@@ -2,6 +2,8 @@
 // for details. All 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._internal;
 
 /**
diff --git a/sdk_nnbd/lib/internal/linked_list.dart b/sdk_nnbd/lib/internal/linked_list.dart
index 31a6c01..5c2e79a 100644
--- a/sdk_nnbd/lib/internal/linked_list.dart
+++ b/sdk_nnbd/lib/internal/linked_list.dart
@@ -2,6 +2,8 @@
 // for details. All 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._internal;
 
 /// A rudimentary linked list.
diff --git a/sdk_nnbd/lib/internal/list.dart b/sdk_nnbd/lib/internal/list.dart
index e0ddd70..be15f36 100644
--- a/sdk_nnbd/lib/internal/list.dart
+++ b/sdk_nnbd/lib/internal/list.dart
@@ -2,6 +2,8 @@
 // for details. All 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._internal;
 
 /**
diff --git a/sdk_nnbd/lib/internal/patch.dart b/sdk_nnbd/lib/internal/patch.dart
index 3fc9733..1d05fda 100644
--- a/sdk_nnbd/lib/internal/patch.dart
+++ b/sdk_nnbd/lib/internal/patch.dart
@@ -2,6 +2,8 @@
 // for details. All 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:_internal";
 
 class _Patch {
diff --git a/sdk_nnbd/lib/internal/print.dart b/sdk_nnbd/lib/internal/print.dart
index 417003b..ce5bb2a 100644
--- a/sdk_nnbd/lib/internal/print.dart
+++ b/sdk_nnbd/lib/internal/print.dart
@@ -2,6 +2,8 @@
 // for details. All 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._internal;
 
 /**
diff --git a/sdk_nnbd/lib/internal/sort.dart b/sdk_nnbd/lib/internal/sort.dart
index d6cca2e..ad79811 100644
--- a/sdk_nnbd/lib/internal/sort.dart
+++ b/sdk_nnbd/lib/internal/sort.dart
@@ -2,6 +2,8 @@
 // for details. All 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._internal;
 
 /**
diff --git a/sdk_nnbd/lib/internal/symbol.dart b/sdk_nnbd/lib/internal/symbol.dart
index 54d235c..d6f05d7 100644
--- a/sdk_nnbd/lib/internal/symbol.dart
+++ b/sdk_nnbd/lib/internal/symbol.dart
@@ -2,6 +2,8 @@
 // for details. All 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._internal;
 
 /**
diff --git a/sdk_nnbd/lib/io/bytes_builder.dart b/sdk_nnbd/lib/io/bytes_builder.dart
index 9113d44..719b85a 100644
--- a/sdk_nnbd/lib/io/bytes_builder.dart
+++ b/sdk_nnbd/lib/io/bytes_builder.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.io;
 
 /**
diff --git a/sdk_nnbd/lib/io/common.dart b/sdk_nnbd/lib/io/common.dart
index 77b7587..1635f56 100644
--- a/sdk_nnbd/lib/io/common.dart
+++ b/sdk_nnbd/lib/io/common.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.io;
 
 // Constants used when working with native ports.
diff --git a/sdk_nnbd/lib/io/data_transformer.dart b/sdk_nnbd/lib/io/data_transformer.dart
index 33c615d..0df0b62 100644
--- a/sdk_nnbd/lib/io/data_transformer.dart
+++ b/sdk_nnbd/lib/io/data_transformer.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 
 /**
diff --git a/sdk_nnbd/lib/io/directory.dart b/sdk_nnbd/lib/io/directory.dart
index 2f141cb..b655779 100644
--- a/sdk_nnbd/lib/io/directory.dart
+++ b/sdk_nnbd/lib/io/directory.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 
 /**
diff --git a/sdk_nnbd/lib/io/directory_impl.dart b/sdk_nnbd/lib/io/directory_impl.dart
index faed892..9f6b907 100644
--- a/sdk_nnbd/lib/io/directory_impl.dart
+++ b/sdk_nnbd/lib/io/directory_impl.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.io;
 
 class _Directory extends FileSystemEntity implements Directory {
diff --git a/sdk_nnbd/lib/io/embedder_config.dart b/sdk_nnbd/lib/io/embedder_config.dart
index cbc94f7..2248d1b 100644
--- a/sdk_nnbd/lib/io/embedder_config.dart
+++ b/sdk_nnbd/lib/io/embedder_config.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 
 /// Embedder-specific, fine-grained dart:io configuration.
diff --git a/sdk_nnbd/lib/io/eventhandler.dart b/sdk_nnbd/lib/io/eventhandler.dart
index 36f54e6..90f22a6 100644
--- a/sdk_nnbd/lib/io/eventhandler.dart
+++ b/sdk_nnbd/lib/io/eventhandler.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 
 class _EventHandler {
diff --git a/sdk_nnbd/lib/io/file.dart b/sdk_nnbd/lib/io/file.dart
index 861ce47..6e515ea 100644
--- a/sdk_nnbd/lib/io/file.dart
+++ b/sdk_nnbd/lib/io/file.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 
 /**
diff --git a/sdk_nnbd/lib/io/file_impl.dart b/sdk_nnbd/lib/io/file_impl.dart
index 410182c..3d302cc 100644
--- a/sdk_nnbd/lib/io/file_impl.dart
+++ b/sdk_nnbd/lib/io/file_impl.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.io;
 
 // Read the file in blocks of size 64k.
diff --git a/sdk_nnbd/lib/io/file_system_entity.dart b/sdk_nnbd/lib/io/file_system_entity.dart
index 16e99e6..871cfd9 100644
--- a/sdk_nnbd/lib/io/file_system_entity.dart
+++ b/sdk_nnbd/lib/io/file_system_entity.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 
 /**
diff --git a/sdk_nnbd/lib/io/io.dart b/sdk_nnbd/lib/io/io.dart
index c640c5b..05df370 100644
--- a/sdk_nnbd/lib/io/io.dart
+++ b/sdk_nnbd/lib/io/io.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 /**
  * File, socket, HTTP, and other I/O support for non-web applications.
  *
diff --git a/sdk_nnbd/lib/io/io_resource_info.dart b/sdk_nnbd/lib/io/io_resource_info.dart
index 3e29221..8426483 100644
--- a/sdk_nnbd/lib/io/io_resource_info.dart
+++ b/sdk_nnbd/lib/io/io_resource_info.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.io;
 
 abstract class _IOResourceInfo {
diff --git a/sdk_nnbd/lib/io/io_service.dart b/sdk_nnbd/lib/io/io_service.dart
index 7af382c..b572def 100644
--- a/sdk_nnbd/lib/io/io_service.dart
+++ b/sdk_nnbd/lib/io/io_service.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 
 class _IOService {
diff --git a/sdk_nnbd/lib/io/io_sink.dart b/sdk_nnbd/lib/io/io_sink.dart
index 5481265..8331dd0 100644
--- a/sdk_nnbd/lib/io/io_sink.dart
+++ b/sdk_nnbd/lib/io/io_sink.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.io;
 
 /**
diff --git a/sdk_nnbd/lib/io/link.dart b/sdk_nnbd/lib/io/link.dart
index 79f8656..0ff9e9d 100644
--- a/sdk_nnbd/lib/io/link.dart
+++ b/sdk_nnbd/lib/io/link.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 
 /**
diff --git a/sdk_nnbd/lib/io/namespace_impl.dart b/sdk_nnbd/lib/io/namespace_impl.dart
index 88987b6..1bac5a2 100644
--- a/sdk_nnbd/lib/io/namespace_impl.dart
+++ b/sdk_nnbd/lib/io/namespace_impl.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.io;
 
 // Each Isolate may run in a different "namespace", which provides the scope in
diff --git a/sdk_nnbd/lib/io/overrides.dart b/sdk_nnbd/lib/io/overrides.dart
index 1a71881..6786ae4 100644
--- a/sdk_nnbd/lib/io/overrides.dart
+++ b/sdk_nnbd/lib/io/overrides.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 
 final _ioOverridesToken = new Object();
diff --git a/sdk_nnbd/lib/io/platform.dart b/sdk_nnbd/lib/io/platform.dart
index f7c9053..c08b937 100644
--- a/sdk_nnbd/lib/io/platform.dart
+++ b/sdk_nnbd/lib/io/platform.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.io;
 
 /**
diff --git a/sdk_nnbd/lib/io/platform_impl.dart b/sdk_nnbd/lib/io/platform_impl.dart
index a350119..c7b23a9 100644
--- a/sdk_nnbd/lib/io/platform_impl.dart
+++ b/sdk_nnbd/lib/io/platform_impl.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.io;
 
 class _Platform {
diff --git a/sdk_nnbd/lib/io/process.dart b/sdk_nnbd/lib/io/process.dart
index 4cf78b9..b503e9e 100644
--- a/sdk_nnbd/lib/io/process.dart
+++ b/sdk_nnbd/lib/io/process.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 
 // TODO(ager): The only reason for this class is that we
diff --git a/sdk_nnbd/lib/io/secure_server_socket.dart b/sdk_nnbd/lib/io/secure_server_socket.dart
index b4ca32e..4b84859 100644
--- a/sdk_nnbd/lib/io/secure_server_socket.dart
+++ b/sdk_nnbd/lib/io/secure_server_socket.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 
 /**
diff --git a/sdk_nnbd/lib/io/secure_socket.dart b/sdk_nnbd/lib/io/secure_socket.dart
index a4751ef..e9b5759 100644
--- a/sdk_nnbd/lib/io/secure_socket.dart
+++ b/sdk_nnbd/lib/io/secure_socket.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 
 /**
diff --git a/sdk_nnbd/lib/io/security_context.dart b/sdk_nnbd/lib/io/security_context.dart
index 96da93b..78a4569 100644
--- a/sdk_nnbd/lib/io/security_context.dart
+++ b/sdk_nnbd/lib/io/security_context.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart.io;
 
 /**
diff --git a/sdk_nnbd/lib/io/service_object.dart b/sdk_nnbd/lib/io/service_object.dart
index e6b1851..54db0ea 100644
--- a/sdk_nnbd/lib/io/service_object.dart
+++ b/sdk_nnbd/lib/io/service_object.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 
 int _nextServiceId = 1;
diff --git a/sdk_nnbd/lib/io/socket.dart b/sdk_nnbd/lib/io/socket.dart
index df60490..c3583de 100644
--- a/sdk_nnbd/lib/io/socket.dart
+++ b/sdk_nnbd/lib/io/socket.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 
 /**
diff --git a/sdk_nnbd/lib/io/stdio.dart b/sdk_nnbd/lib/io/stdio.dart
index 4086f08..c1aacba 100644
--- a/sdk_nnbd/lib/io/stdio.dart
+++ b/sdk_nnbd/lib/io/stdio.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 
 const int _stdioHandleTypeTerminal = 0;
diff --git a/sdk_nnbd/lib/io/string_transformer.dart b/sdk_nnbd/lib/io/string_transformer.dart
index f31c41e..e8548d1 100644
--- a/sdk_nnbd/lib/io/string_transformer.dart
+++ b/sdk_nnbd/lib/io/string_transformer.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 
 /// The current system encoding.
diff --git a/sdk_nnbd/lib/io/sync_socket.dart b/sdk_nnbd/lib/io/sync_socket.dart
index fee259d..0b7d5b1 100644
--- a/sdk_nnbd/lib/io/sync_socket.dart
+++ b/sdk_nnbd/lib/io/sync_socket.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 
 /**
diff --git a/sdk_nnbd/lib/isolate/capability.dart b/sdk_nnbd/lib/isolate/capability.dart
index a51eec2..7f1daa6 100644
--- a/sdk_nnbd/lib/isolate/capability.dart
+++ b/sdk_nnbd/lib/isolate/capability.dart
@@ -2,6 +2,8 @@
 // for details. All 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.isolate;
 
 /**
diff --git a/sdk_nnbd/lib/isolate/isolate.dart b/sdk_nnbd/lib/isolate/isolate.dart
index a697db4..11240ad 100644
--- a/sdk_nnbd/lib/isolate/isolate.dart
+++ b/sdk_nnbd/lib/isolate/isolate.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 /**
  * Concurrent programming using _isolates_:
  * independent workers that are similar to threads
diff --git a/sdk_nnbd/lib/js/_js.dart b/sdk_nnbd/lib/js/_js.dart
index aef7ef9..d0d51f6 100644
--- a/sdk_nnbd/lib/js/_js.dart
+++ b/sdk_nnbd/lib/js/_js.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 /// Helper library used by `dart:js`.
 ///
 /// This library hides any logic that is specific to the web, and allows us to
diff --git a/sdk_nnbd/lib/js/_js_client.dart b/sdk_nnbd/lib/js/_js_client.dart
index de25540..e81821a 100644
--- a/sdk_nnbd/lib/js/_js_client.dart
+++ b/sdk_nnbd/lib/js/_js_client.dart
@@ -2,6 +2,8 @@
 // for details. All 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:html' show Blob, Event, ImageData, Node, Window, WorkerGlobalScope;
 import 'dart:indexed_db' show KeyRange;
 import 'dart:_js_helper' show patch;
diff --git a/sdk_nnbd/lib/js/_js_server.dart b/sdk_nnbd/lib/js/_js_server.dart
index b941d77..8ca6a02 100644
--- a/sdk_nnbd/lib/js/_js_server.dart
+++ b/sdk_nnbd/lib/js/_js_server.dart
@@ -2,6 +2,8 @@
 // for details. All 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:_js_helper' show patch;
 
 @patch
diff --git a/sdk_nnbd/lib/js/dart2js/js_dart2js.dart b/sdk_nnbd/lib/js/dart2js/js_dart2js.dart
index 535227b..4155113 100644
--- a/sdk_nnbd/lib/js/dart2js/js_dart2js.dart
+++ b/sdk_nnbd/lib/js/dart2js/js_dart2js.dart
@@ -2,85 +2,88 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/**
- * Support for interoperating with JavaScript.
- *
- * This library provides access to JavaScript objects from Dart, allowing
- * Dart code to get and set properties, and call methods of JavaScript objects
- * and invoke JavaScript functions. The library takes care of converting
- * between Dart and JavaScript objects where possible, or providing proxies if
- * conversion isn't possible.
- *
- * This library does not yet make Dart objects usable from JavaScript, their
- * methods and proeprties are not accessible, though it does allow Dart
- * functions to be passed into and called from JavaScript.
- *
- * [JsObject] is the core type and represents a proxy of a JavaScript object.
- * JsObject gives access to the underlying JavaScript objects properties and
- * methods. `JsObject`s can be acquired by calls to JavaScript, or they can be
- * created from proxies to JavaScript constructors.
- *
- * The top-level getter [context] provides a [JsObject] that represents the
- * global object in JavaScript, usually `window`.
- *
- * The following example shows an alert dialog via a JavaScript call to the
- * global function `alert()`:
- *
- *     import 'dart:js';
- *
- *     main() => context.callMethod('alert', ['Hello from Dart!']);
- *
- * This example shows how to create a [JsObject] from a JavaScript constructor
- * and access its properties:
- *
- *     import 'dart:js';
- *
- *     main() {
- *       var object = new JsObject(context['Object']);
- *       object['greeting'] = 'Hello';
- *       object['greet'] = (name) => "${object['greeting']} $name";
- *       var message = object.callMethod('greet', ['JavaScript']);
- *       context['console'].callMethod('log', [message]);
- *     }
- *
- * ## Proxying and automatic conversion
- *
- * When setting properties on a JsObject or passing arguments to a Javascript
- * method or function, Dart objects are automatically converted or proxied to
- * JavaScript objects. When accessing JavaScript properties, or when a Dart
- * closure is invoked from JavaScript, the JavaScript objects are also
- * converted to Dart.
- *
- * Functions and closures are proxied in such a way that they are callable. A
- * Dart closure assigned to a JavaScript property is proxied by a function in
- * JavaScript. A JavaScript function accessed from Dart is proxied by a
- * [JsFunction], which has a [apply] method to invoke it.
- *
- * The following types are transferred directly and not proxied:
- *
- *   * Basic types: `null`, `bool`, `num`, `String`, `DateTime`
- *   * `TypedData`, including its subclasses like `Int32List`, but _not_
- *     `ByteBuffer`
- *   * When compiling for the web, also: `Blob`, `Event`, `ImageData`,
- *     `KeyRange`, `Node`, and `Window`.
- *
- * ## Converting collections with JsObject.jsify()
- *
- * To create a JavaScript collection from a Dart collection use the
- * [JsObject.jsify] constructor, which converts Dart [Map]s and [Iterable]s
- * into JavaScript Objects and Arrays.
- *
- * The following expression creates a new JavaScript object with the properties
- * `a` and `b` defined:
- *
- *     var jsMap = new JsObject.jsify({'a': 1, 'b': 2});
- *
- * This expression creates a JavaScript array:
- *
- *     var jsArray = new JsObject.jsify([1, 2, 3]);
- *
- * {@category Web}
- */
+// @dart = 2.5
+
+/// Low-level support for interoperating with JavaScript.
+///
+/// You should usually use `package:js` instead of this library. For more
+/// information, see the [JS interop page](https://dart.dev/web/js-interop).
+///
+/// This library provides access to JavaScript objects from Dart, allowing
+/// Dart code to get and set properties, and call methods of JavaScript objects
+/// and invoke JavaScript functions. The library takes care of converting
+/// between Dart and JavaScript objects where possible, or providing proxies if
+/// conversion isn't possible.
+///
+/// This library does not make Dart objects usable from JavaScript, their
+/// methods and properties are not accessible, though it does allow Dart
+/// functions to be passed into and called from JavaScript.
+///
+/// [JsObject] is the core type and represents a proxy of a JavaScript object.
+/// JsObject gives access to the underlying JavaScript objects properties and
+/// methods. `JsObject`s can be acquired by calls to JavaScript, or they can be
+/// created from proxies to JavaScript constructors.
+///
+/// The top-level getter [context] provides a [JsObject] that represents the
+/// global object in JavaScript, usually `window`.
+///
+/// The following example shows an alert dialog via a JavaScript call to the
+/// global function `alert()`:
+///
+///     import 'dart:js';
+///
+///     main() => context.callMethod('alert', ['Hello from Dart!']);
+///
+/// This example shows how to create a [JsObject] from a JavaScript constructor
+/// and access its properties:
+///
+///     import 'dart:js';
+///
+///     main() {
+///       var object = JsObject(context['Object']);
+///       object['greeting'] = 'Hello';
+///       object['greet'] = (name) => "${object['greeting']} $name";
+///       var message = object.callMethod('greet', ['JavaScript']);
+///       context['console'].callMethod('log', [message]);
+///     }
+///
+/// ## Proxying and automatic conversion
+///
+/// When setting properties on a JsObject or passing arguments to a Javascript
+/// method or function, Dart objects are automatically converted or proxied to
+/// JavaScript objects. When accessing JavaScript properties, or when a Dart
+/// closure is invoked from JavaScript, the JavaScript objects are also
+/// converted to Dart.
+///
+/// Functions and closures are proxied in such a way that they are callable. A
+/// Dart closure assigned to a JavaScript property is proxied by a function in
+/// JavaScript. A JavaScript function accessed from Dart is proxied by a
+/// [JsFunction], which has a [apply] method to invoke it.
+///
+/// The following types are transferred directly and not proxied:
+///
+///   * Basic types: `null`, `bool`, `num`, `String`, `DateTime`
+///   * `TypedData`, including its subclasses like `Int32List`, but _not_
+///     `ByteBuffer`
+///   * When compiling for the web, also: `Blob`, `Event`, `ImageData`,
+///     `KeyRange`, `Node`, and `Window`.
+///
+/// ## Converting collections with JsObject.jsify()
+///
+/// To create a JavaScript collection from a Dart collection use the
+/// [JsObject.jsify] constructor, which converts Dart [Map]s and [Iterable]s
+/// into JavaScript Objects and Arrays.
+///
+/// The following expression creates a new JavaScript object with the properties
+/// `a` and `b` defined:
+///
+///     var jsMap = JsObject.jsify({'a': 1, 'b': 2});
+///
+/// This expression creates a JavaScript array:
+///
+///     var jsArray = JsObject.jsify([1, 2, 3]);
+///
+/// {@category Web}
 library dart.js;
 
 import 'dart:collection' show HashMap, ListMixin;
@@ -99,6 +102,7 @@
 
 export 'dart:_interceptors' show JavaScriptObject;
 
+/// The JavaScript global object, usually `window`.
 final JsObject context = _wrapToDart(JS('', 'self'));
 
 _convertDartFunction(Function f, {bool captureThis: false}) {
@@ -121,56 +125,51 @@
   if (captureThis) {
     arguments = [self]..addAll(arguments);
   }
-  var dartArgs = new List.from(arguments.map(_convertToDart));
+  var dartArgs = List.from(arguments.map(_convertToDart));
   return _convertToJS(Function.apply(callback, dartArgs));
 }
 
-/**
- * Proxies a JavaScript object to Dart.
- *
- * The properties of the JavaScript object are accessible via the `[]` and
- * `[]=` operators. Methods are callable via [callMethod].
- */
+/// A proxy on a JavaScript object.
+///
+/// The properties of the JavaScript object are accessible via the `[]` and
+/// `[]=` operators. Methods are callable via [callMethod].
 class JsObject {
   // The wrapped JS object.
   final dynamic _jsObject;
 
-  // This shoud only be called from _wrapToDart
+  // This should only be called from _wrapToDart
   JsObject._fromJs(this._jsObject) {
     assert(_jsObject != null);
   }
 
-  /**
-   * Constructs a new JavaScript object from [constructor] and returns a proxy
-   * to it.
-   */
+  /// Constructs a JavaScript object from its native [constructor] and returns
+  /// a proxy to it.
   factory JsObject(JsFunction constructor, [List arguments]) {
-    var constr = _convertToJS(constructor);
+    var ctor = _convertToJS(constructor);
     if (arguments == null) {
-      return _wrapToDart(JS('', 'new #()', constr));
+      return _wrapToDart(JS('', 'new #()', ctor));
     }
 
     if (JS('bool', '# instanceof Array', arguments)) {
       int argumentCount = JS('int', '#.length', arguments);
       switch (argumentCount) {
         case 0:
-          return _wrapToDart(JS('', 'new #()', constr));
+          return _wrapToDart(JS('', 'new #()', ctor));
 
         case 1:
           var arg0 = _convertToJS(JS('', '#[0]', arguments));
-          return _wrapToDart(JS('', 'new #(#)', constr, arg0));
+          return _wrapToDart(JS('', 'new #(#)', ctor, arg0));
 
         case 2:
           var arg0 = _convertToJS(JS('', '#[0]', arguments));
           var arg1 = _convertToJS(JS('', '#[1]', arguments));
-          return _wrapToDart(JS('', 'new #(#, #)', constr, arg0, arg1));
+          return _wrapToDart(JS('', 'new #(#, #)', ctor, arg0, arg1));
 
         case 3:
           var arg0 = _convertToJS(JS('', '#[0]', arguments));
           var arg1 = _convertToJS(JS('', '#[1]', arguments));
           var arg2 = _convertToJS(JS('', '#[2]', arguments));
-          return _wrapToDart(
-              JS('', 'new #(#, #, #)', constr, arg0, arg1, arg2));
+          return _wrapToDart(JS('', 'new #(#, #, #)', ctor, arg0, arg1, arg2));
 
         case 4:
           var arg0 = _convertToJS(JS('', '#[0]', arguments));
@@ -178,7 +177,7 @@
           var arg2 = _convertToJS(JS('', '#[2]', arguments));
           var arg3 = _convertToJS(JS('', '#[3]', arguments));
           return _wrapToDart(
-              JS('', 'new #(#, #, #, #)', constr, arg0, arg1, arg2, arg3));
+              JS('', 'new #(#, #, #, #)', ctor, arg0, arg1, arg2, arg3));
       }
     }
 
@@ -190,7 +189,7 @@
     // After that, use the JavaScript 'new' operator which overrides any binding
     // of 'this' with the new instance.
     var args = <dynamic>[null]..addAll(arguments.map(_convertToJS));
-    var factoryFunction = JS('', '#.bind.apply(#, #)', constr, constr, args);
+    var factoryFunction = JS('', '#.bind.apply(#, #)', ctor, ctor, args);
     // Without this line, calling factoryFunction as a constructor throws
     JS('String', 'String(#)', factoryFunction);
     // This could return an UnknownJavaScriptObject, or a native
@@ -201,48 +200,44 @@
 
     // TODO(sra): Investigate:
     //
-    //     var jsObj = JS('', 'Object.create(#.prototype)', constr);
-    //     JS('', '#.apply(#, #)', constr, jsObj,
+    //     var jsObj = JS('', 'Object.create(#.prototype)', ctor);
+    //     JS('', '#.apply(#, #)', ctor, jsObj,
     //         []..addAll(arguments.map(_convertToJS)));
     //     return _wrapToDart(jsObj);
   }
 
-  /**
-   * Constructs a [JsObject] that proxies a native Dart object; _for expert use
-   * only_.
-   *
-   * Use this constructor only if you wish to get access to JavaScript
-   * properties attached to a browser host object, such as a Node or Blob, that
-   * is normally automatically converted into a native Dart object.
-   *
-   * An exception will be thrown if [object] either is `null` or has the type
-   * `bool`, `num`, or `String`.
-   */
+  /// Constructs a [JsObject] that proxies a native Dart object; _for expert use
+  /// only_.
+  ///
+  /// Use this constructor only if you wish to get access to JavaScript
+  /// properties attached to a browser host object, such as a Node or Blob, that
+  /// is normally automatically converted into a native Dart object.
+  ///
+  /// An exception will be thrown if [object] either is `null` or has the type
+  /// `bool`, `num`, or `String`.
   factory JsObject.fromBrowserObject(object) {
     if (object is num || object is String || object is bool || object == null) {
-      throw new ArgumentError("object cannot be a num, string, bool, or null");
+      throw ArgumentError("object cannot be a num, string, bool, or null");
     }
     return _wrapToDart(_convertToJS(object));
   }
 
-  /**
-   * Recursively converts a JSON-like collection of Dart objects to a
-   * collection of JavaScript objects and returns a [JsObject] proxy to it.
-   *
-   * [object] must be a [Map] or [Iterable], the contents of which are also
-   * converted. Maps and Iterables are copied to a new JavaScript object.
-   * Primitives and other transferrable values are directly converted to their
-   * JavaScript type, and all other objects are proxied.
-   */
+  /// Recursively converts a JSON-like collection of Dart objects to a
+  /// collection of JavaScript objects and returns a [JsObject] proxy to it.
+  ///
+  /// [object] must be a [Map] or [Iterable], the contents of which are also
+  /// converted. Maps and Iterables are copied to a new JavaScript object.
+  /// Primitives and other transferable values are directly converted to their
+  /// JavaScript type, and all other objects are proxied.
   factory JsObject.jsify(object) {
     if ((object is! Map) && (object is! Iterable)) {
-      throw new ArgumentError("object must be a Map or Iterable");
+      throw ArgumentError("object must be a Map or Iterable");
     }
     return _wrapToDart(_convertDataTree(object));
   }
 
   static _convertDataTree(data) {
-    var _convertedObjects = new HashMap.identity();
+    var _convertedObjects = HashMap.identity();
 
     _convert(o) {
       if (_convertedObjects.containsKey(o)) {
@@ -252,7 +247,7 @@
         final convertedMap = JS('=Object', '{}');
         _convertedObjects[o] = convertedMap;
         for (var key in o.keys) {
-          JS('=Object', '#[#]=#', convertedMap, key, _convert(o[key]));
+          JS('=Object', '#[#] = #', convertedMap, key, _convert(o[key]));
         }
         return convertedMap;
       } else if (o is Iterable) {
@@ -268,30 +263,26 @@
     return _convert(data);
   }
 
-  /**
-   * Returns the value associated with [property] from the proxied JavaScript
-   * object.
-   *
-   * The type of [property] must be either [String] or [num].
-   */
+  /// Returns the value associated with [property] from the proxied JavaScript
+  /// object.
+  ///
+  /// The type of [property] must be either [String] or [num].
   dynamic operator [](property) {
     if (property is! String && property is! num) {
-      throw new ArgumentError("property is not a String or num");
+      throw ArgumentError("property is not a String or num");
     }
     return _convertToDart(JS('', '#[#]', _jsObject, property));
   }
 
-  /**
-   * Sets the value associated with [property] on the proxied JavaScript
-   * object.
-   *
-   * The type of [property] must be either [String] or [num].
-   */
-  operator []=(property, value) {
+  // Sets the value associated with [property] on the proxied JavaScript
+  // object.
+  //
+  // The type of [property] must be either [String] or [num].
+  void operator []=(property, value) {
     if (property is! String && property is! num) {
-      throw new ArgumentError("property is not a String or num");
+      throw ArgumentError("property is not a String or num");
     }
-    JS('', '#[#]=#', _jsObject, property, _convertToJS(value));
+    JS('', '#[#] = #', _jsObject, property, _convertToJS(value));
   }
 
   int get hashCode => 0;
@@ -299,43 +290,35 @@
   bool operator ==(other) =>
       other is JsObject && JS('bool', '# === #', _jsObject, other._jsObject);
 
-  /**
-   * Returns `true` if the JavaScript object contains the specified property
-   * either directly or though its prototype chain.
-   *
-   * This is the equivalent of the `in` operator in JavaScript.
-   */
+  /// Returns `true` if the JavaScript object contains the specified property
+  /// either directly or though its prototype chain.
+  ///
+  /// This is the equivalent of the `in` operator in JavaScript.
   bool hasProperty(property) {
     if (property is! String && property is! num) {
-      throw new ArgumentError("property is not a String or num");
+      throw ArgumentError("property is not a String or num");
     }
     return JS('bool', '# in #', property, _jsObject);
   }
 
-  /**
-   * Removes [property] from the JavaScript object.
-   *
-   * This is the equivalent of the `delete` operator in JavaScript.
-   */
+  /// Removes [property] from the JavaScript object.
+  ///
+  /// This is the equivalent of the `delete` operator in JavaScript.
   void deleteProperty(property) {
     if (property is! String && property is! num) {
-      throw new ArgumentError("property is not a String or num");
+      throw ArgumentError("property is not a String or num");
     }
     JS('bool', 'delete #[#]', _jsObject, property);
   }
 
-  /**
-   * Returns `true` if the JavaScript object has [type] in its prototype chain.
-   *
-   * This is the equivalent of the `instanceof` operator in JavaScript.
-   */
+  /// Returns `true` if the JavaScript object has [type] in its prototype chain.
+  ///
+  /// This is the equivalent of the `instanceof` operator in JavaScript.
   bool instanceof(JsFunction type) {
     return JS('bool', '# instanceof #', _jsObject, _convertToJS(type));
   }
 
-  /**
-   * Returns the result of the JavaScript objects `toString` method.
-   */
+  /// Returns the result of the JavaScript objects `toString` method.
   String toString() {
     try {
       return JS('String', 'String(#)', _jsObject);
@@ -344,66 +327,47 @@
     }
   }
 
-  /**
-   * Calls [method] on the JavaScript object with the arguments [args] and
-   * returns the result.
-   *
-   * The type of [method] must be either [String] or [num].
-   */
+  /// Calls [method] on the JavaScript object with the arguments [args] and
+  /// returns the result.
+  ///
+  /// The type of [method] must be either [String] or [num].
   dynamic callMethod(method, [List args]) {
     if (method is! String && method is! num) {
-      throw new ArgumentError("method is not a String or num");
+      throw ArgumentError("method is not a String or num");
     }
-    return _convertToDart(JS(
-        '',
-        '#[#].apply(#, #)',
-        _jsObject,
-        method,
-        _jsObject,
-        args == null ? null : new List.from(args.map(_convertToJS))));
+    return _convertToDart(JS('', '#[#].apply(#, #)', _jsObject, method,
+        _jsObject, args == null ? null : List.from(args.map(_convertToJS))));
   }
 }
 
-/**
- * Proxies a JavaScript Function object.
- */
+/// A proxy on a JavaScript Function object.
 class JsFunction extends JsObject {
-  /**
-   * Returns a [JsFunction] that captures its 'this' binding and calls [f]
-   * with the value of this passed as the first argument.
-   */
+  /// Returns a [JsFunction] that captures its 'this' binding and calls [f]
+  /// with the value of JavaScript `this` passed as the first argument.
   factory JsFunction.withThis(Function f) {
     var jsFunc = _convertDartFunction(f, captureThis: true);
-    return new JsFunction._fromJs(jsFunc);
+    return JsFunction._fromJs(jsFunc);
   }
 
   JsFunction._fromJs(jsObject) : super._fromJs(jsObject);
 
-  /**
-   * Invokes the JavaScript function with arguments [args]. If [thisArg] is
-   * supplied it is the value of `this` for the invocation.
-   */
+  /// Invokes the JavaScript function with arguments [args]. If [thisArg] is
+  /// supplied it is the value of `this` for the invocation.
   dynamic apply(List args, {thisArg}) => _convertToDart(JS(
       '',
       '#.apply(#, #)',
       _jsObject,
       _convertToJS(thisArg),
-      args == null ? null : new List.from(args.map(_convertToJS))));
+      args == null ? null : List.from(args.map(_convertToJS))));
 }
 
-/**
- * A [List] that proxies a JavaScript array.
- */
+/// A [List] that proxies a JavaScript array.
 class JsArray<E> extends JsObject with ListMixin<E> {
-  /**
-   * Creates a new JavaScript array.
-   */
+  /// Creates an empty JavaScript array.
   JsArray() : super._fromJs([]);
 
-  /**
-   * Creates a new JavaScript array and initializes it to the contents of
-   * [other].
-   */
+  /// Creates a new JavaScript array and initializes it to the contents of
+  /// [other].
   JsArray.from(Iterable<E> other)
       : super._fromJs([]..addAll(other.map(_convertToJS)));
 
@@ -411,22 +375,22 @@
 
   _checkIndex(int index) {
     if (index is int && (index < 0 || index >= length)) {
-      throw new RangeError.range(index, 0, length);
+      throw RangeError.range(index, 0, length);
     }
   }
 
   _checkInsertIndex(int index) {
     if (index is int && (index < 0 || index >= length + 1)) {
-      throw new RangeError.range(index, 0, length);
+      throw RangeError.range(index, 0, length);
     }
   }
 
   static _checkRange(int start, int end, int length) {
     if (start < 0 || start > length) {
-      throw new RangeError.range(start, 0, length);
+      throw RangeError.range(start, 0, length);
     }
     if (end < start || end > length) {
-      throw new RangeError.range(end, start, length);
+      throw RangeError.range(end, start, length);
     }
   }
 
@@ -457,7 +421,7 @@
     if (JS('bool', 'typeof # === "number" && (# >>> 0) === #', len, len, len)) {
       return JS('int', '#', len);
     }
-    throw new StateError('Bad JsArray length');
+    throw StateError('Bad JsArray length');
   }
 
   void set length(int length) {
@@ -473,7 +437,7 @@
   void addAll(Iterable<E> iterable) {
     var list = (JS('bool', '# instanceof Array', iterable))
         ? iterable
-        : new List.from(iterable);
+        : List.from(iterable);
     callMethod('push', list);
   }
 
@@ -488,7 +452,7 @@
   }
 
   E removeLast() {
-    if (length == 0) throw new RangeError(-1);
+    if (length == 0) throw RangeError(-1);
     return callMethod('pop');
   }
 
@@ -501,7 +465,7 @@
     _checkRange(start, end, this.length);
     int length = end - start;
     if (length == 0) return;
-    if (skipCount < 0) throw new ArgumentError(skipCount);
+    if (skipCount < 0) throw ArgumentError(skipCount);
     var args = <dynamic>[start, length]
       ..addAll(iterable.skip(skipCount).take(length));
     callMethod('splice', args);
@@ -612,7 +576,7 @@
     return JS('TypedData', '#', o);
   } else if (JS('bool', '# instanceof Date', o)) {
     var ms = JS('num', '#.getTime()', o);
-    return new DateTime.fromMillisecondsSinceEpoch(ms);
+    return DateTime.fromMillisecondsSinceEpoch(ms);
   } else if (JS('bool', '#.constructor === #', o, _dartProxyCtor)) {
     return JS('', '#.o', o);
   } else {
@@ -623,14 +587,14 @@
 Object _wrapToDart(o) {
   if (JS('bool', 'typeof # == "function"', o)) {
     return _getDartProxy(
-        o, DART_CLOSURE_PROPERTY_NAME, (o) => new JsFunction._fromJs(o));
+        o, DART_CLOSURE_PROPERTY_NAME, (o) => JsFunction._fromJs(o));
   }
   if (JS('bool', '# instanceof Array', o)) {
     return _getDartProxy(
-        o, _DART_OBJECT_PROPERTY_NAME, (o) => new JsArray._fromJs(o));
+        o, _DART_OBJECT_PROPERTY_NAME, (o) => JsArray._fromJs(o));
   }
   return _getDartProxy(
-      o, _DART_OBJECT_PROPERTY_NAME, (o) => new JsObject._fromJs(o));
+      o, _DART_OBJECT_PROPERTY_NAME, (o) => JsObject._fromJs(o));
 }
 
 Object _getDartProxy(o, String propertyName, createProxy(o)) {
@@ -649,9 +613,6 @@
   return dartProxy;
 }
 
-// ---------------------------------------------------------------------------
-// Start of methods for new style Dart-JS interop.
-
 _convertDartFunctionFast(Function f) {
   var existing = JS('', '#.#', f, _JS_FUNCTION_PROPERTY_NAME);
   if (existing != null) return existing;
@@ -698,6 +659,17 @@
   return Function.apply(callback, [self]..addAll(arguments));
 }
 
+/// Returns a wrapper around function [f] that can be called from JavaScript
+/// using `package:js` JavaScript interop.
+///
+/// The calling conventions in Dart2Js differ from JavaScript and so, by
+/// default, it is not possible to call a Dart function directly. Wrapping with
+/// `allowInterop` creates a function that can be called from JavaScript or
+/// Dart. The semantics of the wrapped function are still more strict than
+/// JavaScript, and the function will throw if called with too many or too few
+/// arguments.
+///
+/// Calling this method repeatedly on a function will return the same result.
 F allowInterop<F extends Function>(F f) {
   if (JS('bool', 'typeof(#) == "function"', f)) {
     // Already supports interop, just use the existing function.
@@ -707,10 +679,17 @@
   }
 }
 
+/// Returns a wrapper around function [f] that can be called from JavaScript
+/// using `package:js` JavaScript interop, passing JavaScript `this` as the first
+/// argument.
+///
+/// See [allowInterop].
+///
+/// When called from Dart, [null] will be passed as the first argument.
 Function allowInteropCaptureThis(Function f) {
   if (JS('bool', 'typeof(#) == "function"', f)) {
     // Behavior when the function is already a JS function is unspecified.
-    throw new ArgumentError(
+    throw ArgumentError(
         "Function is already a JS function so cannot capture this.");
     return f;
   } else {
diff --git a/sdk_nnbd/lib/js_util/dart2js/js_util_dart2js.dart b/sdk_nnbd/lib/js_util/dart2js/js_util_dart2js.dart
index 6b605fb..558bdaa 100644
--- a/sdk_nnbd/lib/js_util/dart2js/js_util_dart2js.dart
+++ b/sdk_nnbd/lib/js_util/dart2js/js_util_dart2js.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 /// Utility methods to efficiently manipulate typed JSInterop objects in cases
 /// where the name to call is not known at runtime. You should only use these
 /// methods when the same effect cannot be achieved with @JS annotations.
diff --git a/sdk_nnbd/lib/libraries.json b/sdk_nnbd/lib/libraries.json
index 663991f..a9276e2 100644
--- a/sdk_nnbd/lib/libraries.json
+++ b/sdk_nnbd/lib/libraries.json
@@ -1,153 +1,153 @@
 {
   "comment:0": "NOTE: THIS FILE IS GENERATED. DO NOT EDIT.",
-  "comment:1": "Instead modify 'sdk/lib/libraries.yaml' and follow the instructions therein.",
+  "comment:1": "Instead modify 'sdk_nnbd/lib/libraries.yaml' and follow the instructions therein.",
   "vm": {
     "libraries": {
       "_builtin": {
-        "uri": "../../runtime/bin/builtin.dart"
+        "uri": "_internal/vm/bin/builtin.dart"
       },
       "cli": {
         "patches": [
-          "../../runtime/bin/cli_patch.dart"
+          "_internal/vm/bin/cli_patch.dart"
         ],
         "uri": "cli/cli.dart"
       },
       "core": {
         "patches": [
-          "../../runtime/lib/core_patch.dart",
-          "../../runtime/lib/array.dart",
-          "../../runtime/lib/array_patch.dart",
-          "../../runtime/lib/bigint_patch.dart",
-          "../../runtime/lib/bool_patch.dart",
-          "../../runtime/lib/date_patch.dart",
-          "../../runtime/lib/double.dart",
-          "../../runtime/lib/double_patch.dart",
-          "../../runtime/lib/errors_patch.dart",
-          "../../runtime/lib/expando_patch.dart",
-          "../../runtime/lib/function.dart",
-          "../../runtime/lib/function_patch.dart",
-          "../../runtime/lib/growable_array.dart",
-          "../../runtime/lib/identical_patch.dart",
-          "../../runtime/lib/immutable_map.dart",
-          "../../runtime/lib/integers.dart",
-          "../../runtime/lib/integers_patch.dart",
-          "../../runtime/lib/invocation_mirror_patch.dart",
-          "../../runtime/lib/lib_prefix.dart",
-          "../../runtime/lib/map_patch.dart",
-          "../../runtime/lib/null_patch.dart",
-          "../../runtime/lib/object_patch.dart",
-          "../../runtime/lib/regexp_patch.dart",
-          "../../runtime/lib/stacktrace.dart",
-          "../../runtime/lib/stopwatch_patch.dart",
-          "../../runtime/lib/string_buffer_patch.dart",
-          "../../runtime/lib/string_patch.dart",
-          "../../runtime/lib/type_patch.dart",
-          "../../runtime/lib/uri_patch.dart",
-          "../../runtime/lib/weak_property.dart"
+          "_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": [
-          "../../runtime/lib/async_patch.dart",
-          "../../runtime/lib/deferred_load_patch.dart",
-          "../../runtime/lib/schedule_microtask_patch.dart",
-          "../../runtime/lib/timer_patch.dart"
+          "_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": [
-          "../../runtime/lib/collection_patch.dart",
-          "../../runtime/lib/compact_hash.dart"
+          "_internal/vm/lib/collection_patch.dart",
+          "_internal/vm/lib/compact_hash.dart"
         ],
         "uri": "collection/collection.dart"
       },
       "ffi": {
         "patches": [
-          "../../runtime/lib/ffi_patch.dart",
-          "../../runtime/lib/ffi_dynamic_library_patch.dart",
-          "../../runtime/lib/ffi_native_type_patch.dart"
+          "_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"
       },
-      "wasm": {
-        "patches": [
-          "../../runtime/lib/wasm_patch.dart"
-        ],
-        "uri": "wasm/wasm.dart"
-      },
       "typed_data": {
-        "patches": "../../runtime/lib/typed_data_patch.dart",
+        "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": [
-          "../../runtime/lib/developer.dart",
-          "../../runtime/lib/profiler.dart",
-          "../../runtime/lib/timeline.dart"
+          "_internal/vm/lib/developer.dart",
+          "_internal/vm/lib/profiler.dart",
+          "_internal/vm/lib/timeline.dart"
         ],
         "uri": "developer/developer.dart"
       },
       "isolate": {
         "patches": [
-          "../../runtime/lib/isolate_patch.dart",
-          "../../runtime/lib/timer_impl.dart"
+          "_internal/vm/lib/isolate_patch.dart",
+          "_internal/vm/lib/timer_impl.dart"
         ],
         "uri": "isolate/isolate.dart"
       },
-      "mirrors": {
-        "patches": [
-          "../../runtime/lib/mirrors_patch.dart",
-          "../../runtime/lib/mirrors_impl.dart",
-          "../../runtime/lib/mirror_reference.dart"
-        ],
-        "uri": "mirrors/mirrors.dart"
-      },
       "_vmservice": {
         "uri": "vmservice/vmservice.dart"
       },
+      "wasm": {
+        "patches": [
+          "_internal/vm/lib/wasm_patch.dart"
+        ],
+        "uri": "wasm/wasm.dart"
+      },
       "io": {
         "patches": [
-          "../../runtime/bin/common_patch.dart",
-          "../../runtime/bin/directory_patch.dart",
-          "../../runtime/bin/eventhandler_patch.dart",
-          "../../runtime/bin/file_patch.dart",
-          "../../runtime/bin/file_system_entity_patch.dart",
-          "../../runtime/bin/filter_patch.dart",
-          "../../runtime/bin/io_service_patch.dart",
-          "../../runtime/bin/namespace_patch.dart",
-          "../../runtime/bin/platform_patch.dart",
-          "../../runtime/bin/process_patch.dart",
-          "../../runtime/bin/socket_patch.dart",
-          "../../runtime/bin/stdio_patch.dart",
-          "../../runtime/bin/secure_socket_patch.dart",
-          "../../runtime/bin/sync_socket_patch.dart"
+          "_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": [
-          "../../runtime/lib/internal_patch.dart",
-          "../../runtime/lib/class_id_fasta.dart",
-          "../../runtime/lib/print_patch.dart",
-          "../../runtime/lib/symbol_patch.dart",
+          "_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": "../../runtime/lib/convert_patch.dart",
+        "patches": "_internal/vm/lib/convert_patch.dart",
         "uri": "convert/convert.dart"
       },
       "profiler": {
         "uri": "profiler/profiler.dart"
       },
       "math": {
-        "patches": "../../runtime/lib/math_patch.dart",
+        "patches": "_internal/vm/lib/math_patch.dart",
         "uri": "math/math.dart"
       },
       "_http": {
@@ -487,4 +487,4 @@
       }
     }
   }
-}
+}
\ No newline at end of file
diff --git a/sdk_nnbd/lib/libraries.yaml b/sdk_nnbd/lib/libraries.yaml
index f33a42b..8d56624 100644
--- a/sdk_nnbd/lib/libraries.yaml
+++ b/sdk_nnbd/lib/libraries.yaml
@@ -5,7 +5,7 @@
 # Note: if you edit this file, you must also edit libraries.json in this
 # directory:
 #
-#     python ./tools/yaml2json.py sdk/lib/libraries.yaml sdk/lib/libraries.json
+#     python ./tools/yaml2json.py sdk_nnbd/lib/libraries.yaml sdk_nnbd/lib/libraries.json
 #
 # We currently have several different files that needs to be updated when
 # changing libraries, sources, and patch files.  See
@@ -17,87 +17,87 @@
 vm:
   libraries:
     _builtin:
-      uri: "../../runtime/bin/builtin.dart"
+      uri: "_internal/vm/bin/builtin.dart"
 
     _internal:
       uri: "internal/internal.dart"
       patches:
-        - "../../runtime/lib/internal_patch.dart"
-        - "../../runtime/lib/class_id_fasta.dart"
-        - "../../runtime/lib/print_patch.dart"
-        - "../../runtime/lib/symbol_patch.dart"
+        - "_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"
 
     async:
       uri: "async/async.dart"
       patches:
-        - "../../runtime/lib/async_patch.dart"
-        - "../../runtime/lib/deferred_load_patch.dart"
-        - "../../runtime/lib/schedule_microtask_patch.dart"
-        - "../../runtime/lib/timer_patch.dart"
+        - "_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"
 
     collection:
       uri: "collection/collection.dart"
       patches:
-        - "../../runtime/lib/collection_patch.dart"
-        - "../../runtime/lib/compact_hash.dart"
+        - "_internal/vm/lib/collection_patch.dart"
+        - "_internal/vm/lib/compact_hash.dart"
 
     convert:
       uri: "convert/convert.dart"
-      patches: "../../runtime/lib/convert_patch.dart"
+      patches: "_internal/vm/lib/convert_patch.dart"
 
     core:
       uri: "core/core.dart"
       patches:
-        - "../../runtime/lib/core_patch.dart"
-        - "../../runtime/lib/array.dart"
-        - "../../runtime/lib/array_patch.dart"
-        - "../../runtime/lib/bigint_patch.dart"
-        - "../../runtime/lib/bool_patch.dart"
-        - "../../runtime/lib/date_patch.dart"
-        - "../../runtime/lib/double.dart"
-        - "../../runtime/lib/double_patch.dart"
-        - "../../runtime/lib/errors_patch.dart"
-        - "../../runtime/lib/expando_patch.dart"
-        - "../../runtime/lib/function.dart"
-        - "../../runtime/lib/function_patch.dart"
-        - "../../runtime/lib/growable_array.dart"
-        - "../../runtime/lib/identical_patch.dart"
-        - "../../runtime/lib/immutable_map.dart"
-        - "../../runtime/lib/integers.dart"
-        - "../../runtime/lib/integers_patch.dart"
-        - "../../runtime/lib/invocation_mirror_patch.dart"
-        - "../../runtime/lib/lib_prefix.dart"
-        - "../../runtime/lib/map_patch.dart"
-        - "../../runtime/lib/null_patch.dart"
-        - "../../runtime/lib/object_patch.dart"
-        - "../../runtime/lib/regexp_patch.dart"
-        - "../../runtime/lib/stacktrace.dart"
-        - "../../runtime/lib/stopwatch_patch.dart"
-        - "../../runtime/lib/string_buffer_patch.dart"
-        - "../../runtime/lib/string_patch.dart"
-        - "../../runtime/lib/type_patch.dart"
-        - "../../runtime/lib/uri_patch.dart"
-        - "../../runtime/lib/weak_property.dart"
+        - "_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"
 
     developer:
       uri: "developer/developer.dart"
       patches:
-        - "../../runtime/lib/developer.dart"
-        - "../../runtime/lib/profiler.dart"
-        - "../../runtime/lib/timeline.dart"
+        - "_internal/vm/lib/developer.dart"
+        - "_internal/vm/lib/profiler.dart"
+        - "_internal/vm/lib/timeline.dart"
 
     ffi:
       uri: "ffi/ffi.dart"
       patches:
-        - "../../runtime/lib/ffi_patch.dart"
-        - "../../runtime/lib/ffi_dynamic_library_patch.dart"
-        - "../../runtime/lib/ffi_native_type_patch.dart"
+        - "_internal/vm/lib/ffi_patch.dart"
+        - "_internal/vm/lib/ffi_dynamic_library_patch.dart"
+        - "_internal/vm/lib/ffi_native_type_patch.dart"
 
     wasm:
       uri: "wasm/wasm.dart"
       patches:
-        - "../../runtime/lib/wasm_patch.dart"
+        - "_internal/vm/lib/wasm_patch.dart"
 
     _http:
       uri: "_http/http.dart"
@@ -105,37 +105,37 @@
     io:
       uri: "io/io.dart"
       patches:
-        - "../../runtime/bin/common_patch.dart"
-        - "../../runtime/bin/directory_patch.dart"
-        - "../../runtime/bin/eventhandler_patch.dart"
-        - "../../runtime/bin/file_patch.dart"
-        - "../../runtime/bin/file_system_entity_patch.dart"
-        - "../../runtime/bin/filter_patch.dart"
-        - "../../runtime/bin/io_service_patch.dart"
-        - "../../runtime/bin/namespace_patch.dart"
-        - "../../runtime/bin/platform_patch.dart"
-        - "../../runtime/bin/process_patch.dart"
-        - "../../runtime/bin/socket_patch.dart"
-        - "../../runtime/bin/stdio_patch.dart"
-        - "../../runtime/bin/secure_socket_patch.dart"
-        - "../../runtime/bin/sync_socket_patch.dart"
+        - "_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"
 
     isolate:
       uri: "isolate/isolate.dart"
       patches:
-        - "../../runtime/lib/isolate_patch.dart"
-        - "../../runtime/lib/timer_impl.dart"
+        - "_internal/vm/lib/isolate_patch.dart"
+        - "_internal/vm/lib/timer_impl.dart"
 
     math:
       uri: "math/math.dart"
-      patches: "../../runtime/lib/math_patch.dart"
+      patches: "_internal/vm/lib/math_patch.dart"
 
     mirrors:
       uri: "mirrors/mirrors.dart"
       patches:
-        - "../../runtime/lib/mirrors_patch.dart"
-        - "../../runtime/lib/mirrors_impl.dart"
-        - "../../runtime/lib/mirror_reference.dart"
+        - "_internal/vm/lib/mirrors_patch.dart"
+        - "_internal/vm/lib/mirrors_impl.dart"
+        - "_internal/vm/lib/mirror_reference.dart"
 
     nativewrappers:
       uri: "html/dartium/nativewrappers.dart"
@@ -146,11 +146,11 @@
     cli:
       uri: "cli/cli.dart"
       patches:
-        - "../../runtime/bin/cli_patch.dart"
+        - "_internal/vm/bin/cli_patch.dart"
 
     typed_data:
       uri: "typed_data/typed_data.dart"
-      patches: "../../runtime/lib/typed_data_patch.dart"
+      patches: "_internal/vm/lib/typed_data_patch.dart"
 
     _vmservice:
       uri: "vmservice/vmservice.dart"
diff --git a/sdk_nnbd/lib/math/jenkins_smi_hash.dart b/sdk_nnbd/lib/math/jenkins_smi_hash.dart
index d756b37..0cc69b0 100644
--- a/sdk_nnbd/lib/math/jenkins_smi_hash.dart
+++ b/sdk_nnbd/lib/math/jenkins_smi_hash.dart
@@ -1,6 +1,8 @@
 // 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;
 
 /// This is the [Jenkins hash function][1] but using masking to keep
diff --git a/sdk_nnbd/lib/math/math.dart b/sdk_nnbd/lib/math/math.dart
index 548fb59..16583df 100644
--- a/sdk_nnbd/lib/math/math.dart
+++ b/sdk_nnbd/lib/math/math.dart
@@ -2,6 +2,8 @@
 // for details. All 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 1015e7b..a7c91f6 100644
--- a/sdk_nnbd/lib/math/point.dart
+++ b/sdk_nnbd/lib/math/point.dart
@@ -1,6 +1,8 @@
 // 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;
 
 /// A utility class for representing two-dimensional positions.
diff --git a/sdk_nnbd/lib/math/random.dart b/sdk_nnbd/lib/math/random.dart
index 80e588b..de7d36c 100644
--- a/sdk_nnbd/lib/math/random.dart
+++ b/sdk_nnbd/lib/math/random.dart
@@ -2,6 +2,8 @@
 // for details. All 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.
diff --git a/sdk_nnbd/lib/math/rectangle.dart b/sdk_nnbd/lib/math/rectangle.dart
index 6e72036..0c14d42 100644
--- a/sdk_nnbd/lib/math/rectangle.dart
+++ b/sdk_nnbd/lib/math/rectangle.dart
@@ -1,6 +1,8 @@
 // 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;
 
 /// A base class for representing two-dimensional axis-aligned rectangles.
diff --git a/sdk_nnbd/lib/mirrors/mirrors.dart b/sdk_nnbd/lib/mirrors/mirrors.dart
index 64f88a2..ee68e01 100644
--- a/sdk_nnbd/lib/mirrors/mirrors.dart
+++ b/sdk_nnbd/lib/mirrors/mirrors.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 // For the purposes of the mirrors library, we adopt a naming
 // convention with respect to getters and setters.  Specifically, for
 // some variable or field...
diff --git a/sdk_nnbd/lib/profiler/profiler.dart b/sdk_nnbd/lib/profiler/profiler.dart
deleted file mode 100644
index 1b96dfe..0000000
--- a/sdk_nnbd/lib/profiler/profiler.dart
+++ /dev/null
@@ -1,10 +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.
-
-/// Please see 'dart:developer'.
-@Deprecated("Dart SDK 1.12")
-library dart.profiler;
-
-export 'dart:developer'
-    show getCurrentTag, Counter, Gauge, Metric, Metrics, UserTag;
diff --git a/sdk_nnbd/lib/profiler/profiler_sources.gni b/sdk_nnbd/lib/profiler/profiler_sources.gni
deleted file mode 100644
index adbf447..0000000
--- a/sdk_nnbd/lib/profiler/profiler_sources.gni
+++ /dev/null
@@ -1,8 +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.
-
-profiler_sdk_sources = [
-  "profiler.dart",
-  # The above file needs to be first if additional parts are added to the lib.
-]
diff --git a/sdk_nnbd/lib/svg/dart2js/svg_dart2js.dart b/sdk_nnbd/lib/svg/dart2js/svg_dart2js.dart
index 7966fd7..bdf30e3 100644
--- a/sdk_nnbd/lib/svg/dart2js/svg_dart2js.dart
+++ b/sdk_nnbd/lib/svg/dart2js/svg_dart2js.dart
@@ -1,3 +1,5 @@
+// @dart = 2.5
+
 /**
  * Scalable Vector Graphics:
  * Two-dimensional vector graphics with support for events and animation.
diff --git a/sdk_nnbd/lib/typed_data/typed_data.dart b/sdk_nnbd/lib/typed_data/typed_data.dart
index 89c9496..a5e37bd 100644
--- a/sdk_nnbd/lib/typed_data/typed_data.dart
+++ b/sdk_nnbd/lib/typed_data/typed_data.dart
@@ -2,6 +2,8 @@
 // for details. All 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.
 ///
diff --git a/sdk_nnbd/lib/typed_data/unmodifiable_typed_data.dart b/sdk_nnbd/lib/typed_data/unmodifiable_typed_data.dart
index 3549041..f3def8f 100644
--- a/sdk_nnbd/lib/typed_data/unmodifiable_typed_data.dart
+++ b/sdk_nnbd/lib/typed_data/unmodifiable_typed_data.dart
@@ -2,6 +2,8 @@
 // for details. All 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;
 
 /**
diff --git a/sdk_nnbd/lib/vmservice/asset.dart b/sdk_nnbd/lib/vmservice/asset.dart
index d5772e2..a6b3927 100644
--- a/sdk_nnbd/lib/vmservice/asset.dart
+++ b/sdk_nnbd/lib/vmservice/asset.dart
@@ -2,6 +2,8 @@
 // for details. All 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._vmservice;
 
 class Asset {
diff --git a/sdk_nnbd/lib/vmservice/client.dart b/sdk_nnbd/lib/vmservice/client.dart
index efe33c0..70d978c 100644
--- a/sdk_nnbd/lib/vmservice/client.dart
+++ b/sdk_nnbd/lib/vmservice/client.dart
@@ -2,6 +2,8 @@
 // for details. All 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._vmservice;
 
 typedef void ClientServiceHandle(Message response);
diff --git a/sdk_nnbd/lib/vmservice/constants.dart b/sdk_nnbd/lib/vmservice/constants.dart
index 914576b..5edd3ef 100644
--- a/sdk_nnbd/lib/vmservice/constants.dart
+++ b/sdk_nnbd/lib/vmservice/constants.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// @dart = 2.5
+
 part of dart._vmservice;
 
 // These must be kept in sync with runtime/vm/service.cc.
diff --git a/sdk_nnbd/lib/vmservice/devfs.dart b/sdk_nnbd/lib/vmservice/devfs.dart
index 20e0573..d5ca40f 100644
--- a/sdk_nnbd/lib/vmservice/devfs.dart
+++ b/sdk_nnbd/lib/vmservice/devfs.dart
@@ -2,6 +2,8 @@
 // for details. All 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._vmservice;
 
 String _encodeDevFSDisabledError(Message message) {
diff --git a/sdk_nnbd/lib/vmservice/message.dart b/sdk_nnbd/lib/vmservice/message.dart
index 9e4375a..efe0f06 100644
--- a/sdk_nnbd/lib/vmservice/message.dart
+++ b/sdk_nnbd/lib/vmservice/message.dart
@@ -2,6 +2,8 @@
 // for details. All 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._vmservice;
 
 enum MessageType { Request, Notification, Response }
diff --git a/sdk_nnbd/lib/vmservice/message_router.dart b/sdk_nnbd/lib/vmservice/message_router.dart
index 4c1b307..6c6c746 100644
--- a/sdk_nnbd/lib/vmservice/message_router.dart
+++ b/sdk_nnbd/lib/vmservice/message_router.dart
@@ -2,6 +2,8 @@
 // for details. All 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._vmservice;
 
 abstract class MessageRouter {
diff --git a/sdk_nnbd/lib/vmservice/named_lookup.dart b/sdk_nnbd/lib/vmservice/named_lookup.dart
index 7087c94..a53c57a 100644
--- a/sdk_nnbd/lib/vmservice/named_lookup.dart
+++ b/sdk_nnbd/lib/vmservice/named_lookup.dart
@@ -2,6 +2,8 @@
 // for details. All 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._vmservice;
 
 /// Set like containes which automatically generated String ids for its items
diff --git a/sdk_nnbd/lib/vmservice/running_isolate.dart b/sdk_nnbd/lib/vmservice/running_isolate.dart
index 8a6dd36..cfe9be9 100644
--- a/sdk_nnbd/lib/vmservice/running_isolate.dart
+++ b/sdk_nnbd/lib/vmservice/running_isolate.dart
@@ -2,6 +2,8 @@
 // for details. All 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._vmservice;
 
 class RunningIsolate implements MessageRouter {
diff --git a/sdk_nnbd/lib/vmservice/running_isolates.dart b/sdk_nnbd/lib/vmservice/running_isolates.dart
index 24b155c..e925e03 100644
--- a/sdk_nnbd/lib/vmservice/running_isolates.dart
+++ b/sdk_nnbd/lib/vmservice/running_isolates.dart
@@ -2,6 +2,8 @@
 // for details. All 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._vmservice;
 
 class RunningIsolates implements MessageRouter {
diff --git a/sdk_nnbd/lib/vmservice/vmservice.dart b/sdk_nnbd/lib/vmservice/vmservice.dart
index 0c340ee..c1540ab 100644
--- a/sdk_nnbd/lib/vmservice/vmservice.dart
+++ b/sdk_nnbd/lib/vmservice/vmservice.dart
@@ -2,6 +2,8 @@
 // for details. All 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
+
 library dart._vmservice;
 
 import 'dart:async';
diff --git a/sdk_nnbd/lib/wasm/wasm.dart b/sdk_nnbd/lib/wasm/wasm.dart
index edf0887..631dc22 100644
--- a/sdk_nnbd/lib/wasm/wasm.dart
+++ b/sdk_nnbd/lib/wasm/wasm.dart
@@ -2,12 +2,82 @@
 // for details. All 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
+
 /// {@category VM}
 /// {@nodoc}
 library dart.wasm;
 
-int callWasm(String name, int arg) {
-  return _callWasm(name, arg);
+import 'dart:typed_data';
+
+// Represents the WASM 32-bit int type.
+class Int32 {}
+
+// Represents the WASM 64-bit int type.
+class Int64 {}
+
+// Represents the WASM 32-bit float type.
+class Float {}
+
+// Represents the WASM 64-bit float type.
+class Double {}
+
+// Represents the return type of a void function in WASM.
+class Void {}
+
+// WasmModule is a compiled module that can be instantiated.
+abstract class WasmModule {
+  // Compile a module.
+  external factory WasmModule(Uint8List data);
+
+  // Instantiate the module with the given imports.
+  WasmInstance instantiate(WasmImports imports);
 }
 
-external int _callWasm(String name, int arg);
+// WasmImports holds all the imports for a WasmInstance.
+abstract class WasmImports {
+  // Create an imports object.
+  external factory WasmImports(String moduleName);
+
+  // Add a global variable to the imports.
+  void addGlobal<T>(String name, num value, bool mutable);
+
+  // Add a memory to the imports.
+  void addMemory(String name, WasmMemory memory);
+}
+
+// WasmMemory is a sandbox for a WasmInstance to run in.
+abstract class WasmMemory {
+  // Create a new memory with the given number of initial pages, and optional
+  // maximum number of pages.
+  external factory WasmMemory(int initialPages, [int maxPages]);
+
+  // The WASM spec defines the page size as 64KiB.
+  static const int kPageSizeInBytes = 64 * 1024;
+
+  // Returns the length of the memory in pages.
+  int get lengthInPages;
+
+  // Returns the length of the memory in bytes.
+  int get lengthInBytes;
+
+  // Returns the byte at the given index.
+  int operator [](int index);
+
+  // Sets the byte at the iven index to value.
+  void operator []=(int index, int value);
+
+  // Grow the memory by deltaPages. Returns the number of pages before resizing.
+  int grow(int deltaPages);
+}
+
+// WasmInstance is an instantiated WasmModule.
+abstract class WasmInstance {
+  // Find an exported function with the given signature.
+  WasmFunction<T> lookupFunction<T extends Function>(String name);
+}
+
+// WasmFunction is a callable function in a WasmInstance.
+abstract class WasmFunction<T extends Function> {
+  num call(List<num> args);
+}
diff --git a/sdk_nnbd/lib/web_audio/dart2js/web_audio_dart2js.dart b/sdk_nnbd/lib/web_audio/dart2js/web_audio_dart2js.dart
index ef2ee67..95a7805 100644
--- a/sdk_nnbd/lib/web_audio/dart2js/web_audio_dart2js.dart
+++ b/sdk_nnbd/lib/web_audio/dart2js/web_audio_dart2js.dart
@@ -1,3 +1,5 @@
+// @dart = 2.5
+
 /**
  * High-fidelity audio programming in the browser.
  *
diff --git a/sdk_nnbd/lib/web_gl/dart2js/web_gl_dart2js.dart b/sdk_nnbd/lib/web_gl/dart2js/web_gl_dart2js.dart
index 80e36b1..b7cf4b8 100644
--- a/sdk_nnbd/lib/web_gl/dart2js/web_gl_dart2js.dart
+++ b/sdk_nnbd/lib/web_gl/dart2js/web_gl_dart2js.dart
@@ -1,3 +1,5 @@
+// @dart = 2.5
+
 /**
  * 3D programming in the browser.
  *
diff --git a/sdk_nnbd/lib/web_sql/dart2js/web_sql_dart2js.dart b/sdk_nnbd/lib/web_sql/dart2js/web_sql_dart2js.dart
index 0f703f9..d7a857a 100644
--- a/sdk_nnbd/lib/web_sql/dart2js/web_sql_dart2js.dart
+++ b/sdk_nnbd/lib/web_sql/dart2js/web_sql_dart2js.dart
@@ -1,3 +1,5 @@
+// @dart = 2.5
+
 /**
  * An API for storing data in the browser that can be queried with SQL.
  *
diff --git a/tests/compiler/dart2js/end_to_end/dill_loader_test.dart b/tests/compiler/dart2js/end_to_end/dill_loader_test.dart
index bc2076e..64062ed 100644
--- a/tests/compiler/dart2js/end_to_end/dill_loader_test.dart
+++ b/tests/compiler/dart2js/end_to_end/dill_loader_test.dart
@@ -28,7 +28,7 @@
     Uri entryPoint = Uri.parse('memory:main.dill');
 
     var options = new CompilerOptions()
-      ..target = new Dart2jsTarget("dart2js", new TargetFlags(legacyMode: true))
+      ..target = new Dart2jsTarget("dart2js", new TargetFlags())
       ..packagesFileUri = Uri.base.resolve('.packages')
       ..linkedDependencies = <Uri>[
         computePlatformBinariesLocation().resolve("dart2js_platform.dill"),
diff --git a/tests/compiler/dart2js_extra/constant_folding_test.dart b/tests/compiler/dart2js_extra/constant_folding_test.dart
index af4b614..b9b050b 100644
--- a/tests/compiler/dart2js_extra/constant_folding_test.dart
+++ b/tests/compiler/dart2js_extra/constant_folding_test.dart
@@ -387,6 +387,7 @@
   const TruncatingDivide(-9007199254740991, 0.5, -18014398509481982).check();
   const TruncatingDivide(-9007199254740991, -0.5, 18014398509481982).check();
   const TruncatingDivide(0x8000000000000000, -1, -0x8000000000000000).check();
+  const TruncatingDivide(0x6000000000000000, 0.5, 0xC000000000000000).check();
   const TruncatingDivide(2.71828, 3.14159, 0).check();
   const TruncatingDivide(2.71828, 1, 2).check();
   const TruncatingDivide(2.71828, -1, -2).check();
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index 04290fc..f11deb7 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -50,9 +50,6 @@
 [ $runtime == jsshell ]
 string_case_test/01: Fail, OK # German double S.
 
-[ $runtime != none ]
-nsm_invocation_generic_test: RuntimeError # Not implemented yet. Issue 27323.
-
 [ $runtime == safari ]
 double_round3_test: Fail, OK # Runtime rounds 0.49999999999999994 to 1.
 double_round_to_double2_test: Fail, OK # Runtime rounds 0.49999999999999994 to 1.
diff --git a/tests/corelib_2/int_from_environment_test.dart b/tests/corelib_2/int_from_environment_test.dart
index 62b1f1a..2e6d28e 100644
--- a/tests/corelib_2/int_from_environment_test.dart
+++ b/tests/corelib_2/int_from_environment_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-// SharedOptions=-Da=1 -Db=-12 -Dc=0x123 -Dd=-0x1234 -De=+0x112296 -Df=-9007199254740991 -Dg=9007199254740991
+// SharedOptions=-Da=1 -Db=-12 -Dc=0x123 -Dd=-0x1234 -De=+0x112296 -Df=-9007199254740991 -Dg=9007199254740991 -Dh=-0x8000000000000000 -Di=0x8000000000000000 -Dj=0xDEADBEEFCAFE0000
 
 import "package:expect/expect.dart";
 
@@ -13,4 +13,7 @@
   Expect.equals(0x112296, const int.fromEnvironment('e'));
   Expect.equals(-9007199254740991, const int.fromEnvironment('f'));
   Expect.equals(9007199254740991, const int.fromEnvironment('g'));
+  Expect.equals(-0x8000000000000000, const int.fromEnvironment('h'));
+  Expect.equals(0x8000000000000000, const int.fromEnvironment('i'));
+  Expect.equals(0xDEADBEEFCAFE0000, const int.fromEnvironment('j'));
 }
diff --git a/tests/corelib_2/nsm_invocation_generic_test.dart b/tests/corelib_2/nsm_invocation_generic_test.dart
index 5813857..5d899d0 100644
--- a/tests/corelib_2/nsm_invocation_generic_test.dart
+++ b/tests/corelib_2/nsm_invocation_generic_test.dart
@@ -19,7 +19,7 @@
       nsm.name<int>(arg: argument));
   expectInvocation(
       new Invocation.genericMethod(#name, [int], [argument], {#arg: argument2}),
-      nsm.name<int>(argument, arg: argument));
+      nsm.name<int>(argument, arg: argument2));
   // Call invocation.
   expectInvocation(new Invocation.genericMethod(#call, [int], []), nsm<int>());
   expectInvocation(new Invocation.genericMethod(#call, [int], [argument]),
@@ -29,7 +29,7 @@
       nsm<int>(arg: argument));
   expectInvocation(
       new Invocation.genericMethod(#call, [int], [argument], {#arg: argument2}),
-      nsm<int>(argument, arg: argument));
+      nsm<int>(argument, arg: argument2));
 }
 
 dynamic nsm = new Recorder();
diff --git a/tests/ffi/ffi.status b/tests/ffi/ffi.status
index 46f4755..a6caf81 100644
--- a/tests/ffi/ffi.status
+++ b/tests/ffi/ffi.status
@@ -36,3 +36,6 @@
 
 [ $arch == simarm || $arch == simarm64 ]
 *: Skip # FFI not yet supported on the arm simulator.
+
+[ $system == android ]
+*: Slow # https://github.com/dart-lang/sdk/issues/38489
diff --git a/tests/ffi/function_callbacks_test.dart b/tests/ffi/function_callbacks_test.dart
index 1c5eca5..ca2197f 100644
--- a/tests/ffi/function_callbacks_test.dart
+++ b/tests/ffi/function_callbacks_test.dart
@@ -8,6 +8,10 @@
 // VMOptions=--enable-testing-pragmas --stacktrace-every=100
 // VMOptions=--enable-testing-pragmas --write-protect-code --no-dual-map-code
 // VMOptions=--enable-testing-pragmas --write-protect-code --no-dual-map-code --stacktrace-every=100
+// VMOptions=--use-slow-path --enable-testing-pragmas
+// VMOptions=--use-slow-path --enable-testing-pragmas --stacktrace-every=100
+// VMOptions=--use-slow-path --enable-testing-pragmas --write-protect-code --no-dual-map-code
+// VMOptions=--use-slow-path --enable-testing-pragmas --write-protect-code --no-dual-map-code --stacktrace-every=100
 // SharedObjects=ffi_test_functions
 
 library FfiTest;
diff --git a/tests/language_2/call_method_implicit_tear_off_implements_function_test.dart b/tests/language_2/call_method_implicit_tear_off_implements_function_test.dart
deleted file mode 100644
index 610baab..0000000
--- a/tests/language_2/call_method_implicit_tear_off_implements_function_test.dart
+++ /dev/null
@@ -1,103 +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.
-// Dart test program to test arithmetic operations.
-
-import "dart:async";
-import "package:expect/expect.dart";
-
-class B {}
-
-class C implements Function {
-  B call(B b) => b;
-}
-
-typedef B BToB(B x);
-
-typedef Object NullToObject(Null x);
-
-C c = new C();
-
-void check1(BToB f) {
-  Expect.isFalse(identical(c, f));
-  Expect.equals(c.call, f);
-  B b = new B();
-  Expect.identical(f(b), b);
-}
-
-void check2(FutureOr<BToB> f) {
-  Expect.isFalse(identical(c, f));
-  Expect.equals(c.call, f);
-  BToB f2 = f;
-  B b = new B();
-  Expect.identical(f2(b), b);
-}
-
-void check3(NullToObject f) {
-  Expect.isFalse(identical(c, f));
-  Expect.equals(c.call, f);
-  Expect.isNull(f(null));
-}
-
-void check4(FutureOr<NullToObject> f) {
-  Expect.isFalse(identical(c, f));
-  Expect.equals(c.call, f);
-  NullToObject f2 = f;
-  Expect.isNull(f2(null));
-}
-
-void check5(Function f) {
-  Expect.isFalse(identical(c, f));
-  Expect.equals(c.call, f);
-  B b = new B();
-  Expect.identical(f(b), b);
-}
-
-void check6(FutureOr<Function> f) {
-  Expect.isFalse(identical(c, f));
-  Expect.equals(c.call, f);
-  B b = new B();
-  Function f2 = f;
-  Expect.identical(f2(b), b);
-}
-
-void check7(C x) {
-  Expect.identical(c, x);
-}
-
-void check8(FutureOr<C> x) {
-  Expect.identical(c, x);
-}
-
-void check9(Object o) {
-  Expect.identical(c, o);
-}
-
-void check10(FutureOr<Object> o) {
-  Expect.identical(c, o);
-}
-
-void check11(dynamic d) {
-  Expect.identical(c, d);
-}
-
-void check12(FutureOr<dynamic> d) {
-  Expect.identical(c, d);
-}
-
-main() {
-  // Implicitly tears off c.call
-  check1(c); //# 01: ok
-  check2(c); //# 02: ok
-  check3(c); //# 03: ok
-  check4(c); //# 04: ok
-  check5(c); //# 05: ok
-  check6(c); //# 06: ok
-  // Does not tear off c.call
-  check7(c); //# 07: ok
-  check8(c); //# 08: ok
-  check9(c); //# 09: ok
-  check10(c); //# 10: ok
-  check11(c); //# 11: ok
-  check12(c); //# 12: ok
-}
diff --git a/tests/language_2/config_import_lib1a.dart b/tests/language_2/config_import_lib1a.dart
deleted file mode 100644
index 814c15e..0000000
--- a/tests/language_2/config_import_lib1a.dart
+++ /dev/null
@@ -1,5 +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.
-
-String lib1() => "a";
diff --git a/tests/language_2/config_import_lib1b.dart b/tests/language_2/config_import_lib1b.dart
deleted file mode 100644
index 59212de..0000000
--- a/tests/language_2/config_import_lib1b.dart
+++ /dev/null
@@ -1,5 +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.
-
-String lib1() => "b";
diff --git a/tests/language_2/config_import_lib1c.dart b/tests/language_2/config_import_lib1c.dart
deleted file mode 100644
index 86fd9e9..0000000
--- a/tests/language_2/config_import_lib1c.dart
+++ /dev/null
@@ -1,5 +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.
-
-String lib1() => "c";
diff --git a/tests/language_2/config_import_lib2a.dart b/tests/language_2/config_import_lib2a.dart
deleted file mode 100644
index 00665dd..0000000
--- a/tests/language_2/config_import_lib2a.dart
+++ /dev/null
@@ -1,5 +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.
-
-String lib2() => "a";
diff --git a/tests/language_2/config_import_lib2b.dart b/tests/language_2/config_import_lib2b.dart
deleted file mode 100644
index 6d91daf..0000000
--- a/tests/language_2/config_import_lib2b.dart
+++ /dev/null
@@ -1,5 +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.
-
-String lib2() => "b";
diff --git a/tests/language_2/config_import_lib2c.dart b/tests/language_2/config_import_lib2c.dart
deleted file mode 100644
index 6ed0235..0000000
--- a/tests/language_2/config_import_lib2c.dart
+++ /dev/null
@@ -1,5 +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.
-
-String lib2() => "c";
diff --git a/tests/language_2/config_import_lib3a.dart b/tests/language_2/config_import_lib3a.dart
deleted file mode 100644
index c2f9fec..0000000
--- a/tests/language_2/config_import_lib3a.dart
+++ /dev/null
@@ -1,5 +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.
-
-String lib3() => "a";
diff --git a/tests/language_2/config_import_lib3b.dart b/tests/language_2/config_import_lib3b.dart
deleted file mode 100644
index b6d5afc..0000000
--- a/tests/language_2/config_import_lib3b.dart
+++ /dev/null
@@ -1,5 +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.
-
-String lib3() => "b";
diff --git a/tests/language_2/config_import_lib3c.dart b/tests/language_2/config_import_lib3c.dart
deleted file mode 100644
index b984783..0000000
--- a/tests/language_2/config_import_lib3c.dart
+++ /dev/null
@@ -1,5 +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.
-
-String lib3() => "c";
diff --git a/tests/language_2/config_import_lib4a.dart b/tests/language_2/config_import_lib4a.dart
deleted file mode 100644
index 1607f07..0000000
--- a/tests/language_2/config_import_lib4a.dart
+++ /dev/null
@@ -1,5 +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.
-
-String lib4() => "a";
diff --git a/tests/language_2/config_import_lib4b.dart b/tests/language_2/config_import_lib4b.dart
deleted file mode 100644
index 9e2f08c..0000000
--- a/tests/language_2/config_import_lib4b.dart
+++ /dev/null
@@ -1,5 +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.
-
-String lib4() => "b";
diff --git a/tests/language_2/config_import_lib4c.dart b/tests/language_2/config_import_lib4c.dart
deleted file mode 100644
index f4a1972..0000000
--- a/tests/language_2/config_import_lib4c.dart
+++ /dev/null
@@ -1,5 +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.
-
-String lib4() => "c";
diff --git a/tests/language_2/config_import_test.dart b/tests/language_2/config_import_test.dart
deleted file mode 100644
index 2e15460..0000000
--- a/tests/language_2/config_import_test.dart
+++ /dev/null
@@ -1,30 +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.
-//
-// SharedOptions=-Did=true -Ddotted.id=some_string -Dlots.of.dots.In.id=false
-
-import 'package:expect/expect.dart';
-
-import 'config_import_lib1a.dart'
-    if (id) 'config_import_lib1b.dart'
-    if (not.set.id) 'config_import_lib1c.dart';
-
-import 'config_import_lib2a.dart'
-    if (not.set.id) 'config_import_lib2b.dart'
-    if (not.set.either) 'config_import_lib2c.dart';
-
-import 'config_import_lib3a.dart'
-    if (dotted.id == "some_string") 'config_import_lib3b.dart'
-    if (id) 'config_import_lib3c.dart';
-
-import 'config_import_lib4a.dart'
-    if (lots.of.dots.In.id == "other") 'config_import_lib4b.dart'
-    if (lots.of.dots.In.id == "false") 'config_import_lib4c.dart';
-
-main() {
-  Expect.equals("b", lib1());
-  Expect.equals("a", lib2());
-  Expect.equals("b", lib3());
-  Expect.equals("c", lib4());
-}
diff --git a/tests/language_2/extension_methods/helpers/class_no_shadow.dart b/tests/language_2/extension_methods/helpers/class_no_shadow.dart
index efc929a..cba1e87 100644
--- a/tests/language_2/extension_methods/helpers/class_no_shadow.dart
+++ b/tests/language_2/extension_methods/helpers/class_no_shadow.dart
@@ -19,5 +19,6 @@
   set setterInInstanceScope(String x) {
     checkInstanceValue(x);
   }
+
   String methodInInstanceScope() => instanceValue;
 }
diff --git a/tests/language_2/extension_methods/helpers/class_shadow.dart b/tests/language_2/extension_methods/helpers/class_shadow.dart
index 90bd522..73925be 100644
--- a/tests/language_2/extension_methods/helpers/class_shadow.dart
+++ b/tests/language_2/extension_methods/helpers/class_shadow.dart
@@ -11,11 +11,11 @@
 // A class which has its own instance methods, which also
 // shadows the global scope
 class AGlobal extends A {
-
   String fieldInGlobalScope = instanceValue;
   String get getterInGlobalScope => instanceValue;
   set setterInGlobalScope(String x) {
     checkInstanceValue(x);
   }
+
   String methodInGlobalScope() => instanceValue;
 }
diff --git a/tests/language_2/extension_methods/helpers/extension_all.dart b/tests/language_2/extension_methods/helpers/extension_all.dart
index 1154462..518948d 100644
--- a/tests/language_2/extension_methods/helpers/extension_all.dart
+++ b/tests/language_2/extension_methods/helpers/extension_all.dart
@@ -20,6 +20,7 @@
   set setterInGlobalScope(double x) {
     checkOtherExtensionValue(x);
   }
+
   double methodInGlobalScope() => otherExtensionValue;
 
   double get fieldInInstanceScope => otherExtensionValue;
@@ -27,6 +28,7 @@
   set setterInInstanceScope(double x) {
     checkOtherExtensionValue(x);
   }
+
   double methodInInstanceScope() => otherExtensionValue;
 
   double get fieldInExtensionScope => otherExtensionValue;
@@ -34,6 +36,7 @@
   set setterInExtensionScope(double x) {
     checkOtherExtensionValue(x);
   }
+
   double methodInExtensionScope() => otherExtensionValue;
 
   double get fieldInOtherExtensionScope => otherExtensionValue;
@@ -41,6 +44,6 @@
   set setterInOtherExtensionScope(double x) {
     checkOtherExtensionValue(x);
   }
-  double methodInOtherExtensionScope() => otherExtensionValue;
 
-}
\ No newline at end of file
+  double methodInOtherExtensionScope() => otherExtensionValue;
+}
diff --git a/tests/language_2/extension_methods/helpers/extension_global_instance.dart b/tests/language_2/extension_methods/helpers/extension_global_instance.dart
index a874be0..fd33bcb 100644
--- a/tests/language_2/extension_methods/helpers/extension_global_instance.dart
+++ b/tests/language_2/extension_methods/helpers/extension_global_instance.dart
@@ -20,6 +20,7 @@
   set setterInGlobalScope(double x) {
     checkOtherExtensionValue(x);
   }
+
   double methodInGlobalScope() => otherExtensionValue;
 
   double get fieldInInstanceScope => otherExtensionValue;
@@ -27,6 +28,7 @@
   set setterInInstanceScope(double x) {
     checkOtherExtensionValue(x);
   }
+
   double methodInInstanceScope() => otherExtensionValue;
 
   double get fieldInOtherExtensionScope => otherExtensionValue;
@@ -34,6 +36,6 @@
   set setterInOtherExtensionScope(double x) {
     checkOtherExtensionValue(x);
   }
-  double methodInOtherExtensionScope() => otherExtensionValue;
 
-}
\ No newline at end of file
+  double methodInOtherExtensionScope() => otherExtensionValue;
+}
diff --git a/tests/language_2/extension_methods/helpers/extension_only.dart b/tests/language_2/extension_methods/helpers/extension_only.dart
index fdf55ef..da7d1c4 100644
--- a/tests/language_2/extension_methods/helpers/extension_only.dart
+++ b/tests/language_2/extension_methods/helpers/extension_only.dart
@@ -20,6 +20,6 @@
   set setterInOtherExtensionScope(double x) {
     checkOtherExtensionValue(x);
   }
-  double methodInOtherExtensionScope() => otherExtensionValue;
 
-}
\ No newline at end of file
+  double methodInOtherExtensionScope() => otherExtensionValue;
+}
diff --git a/tests/language_2/extension_methods/helpers/global_scope.dart b/tests/language_2/extension_methods/helpers/global_scope.dart
index 6c98097..2ba1533 100644
--- a/tests/language_2/extension_methods/helpers/global_scope.dart
+++ b/tests/language_2/extension_methods/helpers/global_scope.dart
@@ -18,4 +18,5 @@
 set setterInGlobalScope(int x) {
   checkGlobalValue(x);
 }
+
 int methodInGlobalScope() => globalValue;
diff --git a/tests/language_2/extension_methods/static_extension_bounds_error_test.dart b/tests/language_2/extension_methods/static_extension_bounds_error_test.dart
index 1707f79..04f6825 100644
--- a/tests/language_2/extension_methods/static_extension_bounds_error_test.dart
+++ b/tests/language_2/extension_methods/static_extension_bounds_error_test.dart
@@ -26,7 +26,6 @@
 
 class RecSolution extends Rec<RecSolution> {}
 
-
 void main() {
   String s = "s";
   int i = 0;
@@ -132,4 +131,4 @@
 //   ^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
 // [cfe] unspecified
-}
\ No newline at end of file
+}
diff --git a/tests/language_2/extension_methods/static_extension_getter_setter_conflicts_test.dart b/tests/language_2/extension_methods/static_extension_getter_setter_conflicts_test.dart
index e1baee5..c24bc36 100644
--- a/tests/language_2/extension_methods/static_extension_getter_setter_conflicts_test.dart
+++ b/tests/language_2/extension_methods/static_extension_getter_setter_conflicts_test.dart
@@ -50,8 +50,7 @@
 
 // Conflicting extensions.
 
-class C1<T> {
-}
+class C1<T> {}
 
 extension E1A<T> on C1<T> {
   int get m1 => 0;
@@ -79,7 +78,7 @@
 
   c1a.m2 = 0;
 
-  C1<Object> c1b = C1<Null>();  // Neither extension is more specific.
+  C1<Object> c1b = C1<Null>(); // Neither extension is more specific.
 
   c1b.m1;
   //  ^^
@@ -133,25 +132,6 @@
     this.mc.toRadixString(16);
     // Check that `this.me` refers to `E2.me`.
     this.me.substring(0);
-
-    // An unqualified identifier is matched against the extension (by basename).
-
-    m1 = 0;
-    1 + m1;
-    //  ^^
-    // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_EXTENSION_GETTER
-    // [cfe] unspecified
-
-    1 + m2;
-    if (true) m2 = 0; // for the indent!
-    //        ^^^^^^
-    // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_EXTENSION_SETTER
-    // [cfe] unspecified
-
-    // Check that `mc` refers to `C2.me`.
-    mc.toRadixString(16);
-    // Check that `me` refers to `E2.me`.
-    me.substring(0);
   }
 }
 
diff --git a/tests/language_2/extension_methods/static_extension_getter_setter_test.dart b/tests/language_2/extension_methods/static_extension_getter_setter_test.dart
index 8358a18..e112a87 100644
--- a/tests/language_2/extension_methods/static_extension_getter_setter_test.dart
+++ b/tests/language_2/extension_methods/static_extension_getter_setter_test.dart
@@ -4,7 +4,7 @@
 
 // SharedOptions=--enable-experiment=extension-methods
 
-// Tests interactions between getters and setters where one or both is defined
+// Tests getters and setters where one or both is defined
 // by an extension.
 
 import "package:expect/expect.dart";
@@ -14,37 +14,27 @@
   // v1: C get, C set
   expectGet("C.v1", c.v1);
   expectSet("C.v1=1", c.v1 = Result("1"));
-  // v2: C get, E1 set
+  // v2: C get, E1 get/set, C wins.
   expectGet("C.v2", c.v2);
-  expectSet("E1.v2=2", c.v2 = Result("2"));
-  // v3: E1 get, C set
-  expectGet("E1.v3", c.v3);
+  expectSet("E1.v2=2", E1(c).v2 = Result("2"));
+  // v3: E1 get/set, C set, C wins.
+  expectGet("E1.v3", E1(c).v3);
   expectSet("C.v3=3", c.v3 = Result("3"));
-  // v4: E1 get, E1 set
+  // v4: E1 get/set
   expectGet("E1.v4", c.v4);
   expectSet("E1.v4=4", c.v4 = Result("4"));
-  // v5: E1 get, E2 set
-  expectGet("E1.v5", c.v5);
-  expectSet("E2.v5=5", c.v5 = Result("5"));
+  // v5: E1 get, E2 set, neither more specific.
+  expectGet("E1.v5", E1(c).v5);
+  expectSet("E2.v5=5", E2(c).v5 = Result("5"));
 
   expectSet("C.v1=C.v1+1", c.v1++);
-  expectSet("E1.v2=C.v2+1", c.v2++);
-  expectSet("C.v3=E1.v3+1", c.v3++);
   expectSet("E1.v4=E1.v4+1", c.v4++);
-  expectSet("E2.v5=E1.v5+1", c.v5++);
 
   expectSet("C.v1=C.v1+a", c.v1 += "a");
   expectSet("C.v1=C.v1-b", c.v1 -= "b");
+  expectSet("E1.v4=E1.v4-b", c.v4 -= "b");
 
-  // Cascades work.
-  expectSet(
-      "E1.v4=E2.v4+[C.v1=[E1.v2=a]]",
-      c
-        ..v2 = Result("a")
-        ..v1 = Result("[$lastSetter]")
-        ..v4 += Result("[$lastSetter]"));
-
-  // Override used by all accesses of read/write operations
+  // Explicit application used by all accesses of read/write operations
   expectSet("E1.v1=E1.v1+1", E1(c).v1++);
   expectSet("E1.v2=E1.v2+1", E1(c).v2++);
   expectSet("E1.v3=E1.v3+1", E1(c).v3++);
@@ -56,6 +46,14 @@
   expectSet("E1.v1=E1.v1+1", E1(c).v1 = E1(c).v1 + 1);
   expectSet("E1.v2=E1.v2+1", E1(c).v2 = E1(c).v2 + 1);
   expectSet("E1.v3=E1.v3+1", E1(c).v3 = E1(c).v3 + 1);
+
+  // Cascades work.
+  expectSet(
+      "E1.v4=E1.v4+[C.v1=C.v1-[C.v3=a]]",
+      c
+        ..v3 = Result("a")
+        ..v1 -= Result("[$lastSetter]")
+        ..v4 += Result("[$lastSetter]"));
 }
 
 /// Expect the value of [result] to be the [expected] string
@@ -105,41 +103,41 @@
 /// Declares [v4] getter and setter, and [v5] getter
 /// which are supplemented by a setter from the [E2] extension.
 extension E1 on C {
-  // Overlaps with C on both.
+  // Same basename as C getter and setter.
   Result get v1 => Result("E1.v1");
 
   void set v1(Result value) {
     lastSetter = "E1.v1=$value";
   }
 
-  // Overlaps with C on getter.
+  // Same basename as C getter.
   Result get v2 => Result("E1.v2");
 
   void set v2(Result value) {
     lastSetter = "E1.v2=$value";
   }
 
-  // Overlaps with C on setter.
+  // Same basename as C setter.
   Result get v3 => Result("E1.v3");
 
   void set v3(Result value) {
     lastSetter = "E1.v3=$value";
   }
 
-  // Overlaps with nothing.
+  // No other declarations with same basename.
   Result get v4 => Result("E1.v4");
+
   void set v4(Result value) {
     lastSetter = "E1.v4=$value";
   }
 
-  // Combines with E2 setter.
+  // Same basename as E2 setter.
   Result get v5 => Result("E1.v5");
 }
 
 /// A different extension than [E1] on [C].
 ///
 /// Declares [v5] setter.
-/// Together with [E1], this defined both getter and setter.
 extension E2 on C {
   void set v5(Result value) {
     lastSetter = "E2.v5=$value";
diff --git a/tests/language_2/extension_methods/static_extension_inference_test.dart b/tests/language_2/extension_methods/static_extension_inference_test.dart
index 98fc240..81c90cf 100644
--- a/tests/language_2/extension_methods/static_extension_inference_test.dart
+++ b/tests/language_2/extension_methods/static_extension_inference_test.dart
@@ -172,7 +172,7 @@
   List<T> get argList5 => <T>[];
   List<Object> get argDynList5 => <T>[];
   List<Object> get selfList5 {
-    var result = [this];
+    var result = [self];
     return result;
   }
 }
diff --git a/tests/language_2/extension_methods/static_extension_internal_basename_shadowing_error_test.dart b/tests/language_2/extension_methods/static_extension_internal_basename_shadowing_error_test.dart
index 855cf6d..4158947 100644
--- a/tests/language_2/extension_methods/static_extension_internal_basename_shadowing_error_test.dart
+++ b/tests/language_2/extension_methods/static_extension_internal_basename_shadowing_error_test.dart
@@ -212,7 +212,7 @@
 
 // Define extensions on A6.
 extension E5 on A6 {
-  void set extensionSetter(int _) {};
+  void set extensionSetter(int _) {}
   int extensionMethod(int x) => -3;
 }
 
diff --git a/tests/language_2/extension_methods/static_extension_internal_name_conflict_error_test.dart b/tests/language_2/extension_methods/static_extension_internal_name_conflict_error_test.dart
index 4bd5a29..0e55982 100644
--- a/tests/language_2/extension_methods/static_extension_internal_name_conflict_error_test.dart
+++ b/tests/language_2/extension_methods/static_extension_internal_name_conflict_error_test.dart
@@ -21,7 +21,6 @@
 // [analyzer] COMPILE_TIME_ERROR.DUPLICATE_DEFINITION
 // [cfe] unspecified
 
-
 class E2 {}
 //    ^^
 // [analyzer] COMPILE_TIME_ERROR.DUPLICATE_DEFINITION
@@ -108,7 +107,6 @@
   // [cfe] unspecified
 }
 
-
 // Check static members colliding with static members (of the same kind).
 extension E5 on int {
   static int method() => 0;
@@ -239,4 +237,4 @@
   // [cfe] unspecified
 }
 
-void main() {}
\ No newline at end of file
+void main() {}
diff --git a/tests/language_2/extension_methods/static_extension_internal_resolution_0_test.dart b/tests/language_2/extension_methods/static_extension_internal_resolution_0_test.dart
index 3110880..418ba2b 100644
--- a/tests/language_2/extension_methods/static_extension_internal_resolution_0_test.dart
+++ b/tests/language_2/extension_methods/static_extension_internal_resolution_0_test.dart
@@ -71,10 +71,9 @@
       double t2 = methodInOtherExtensionScope();
       checkOtherExtensionValue(t2);
     }
-
   }
 
-   void testIdentifiersOnThis() {
+  void testIdentifiersOnThis() {
     // Instance members resolve to the instance methods and not the members
     // of the other extension (when present)
     {
@@ -125,7 +124,6 @@
       self.setterInOtherExtensionScope = otherExtensionValue;
       double t2 = self.methodInOtherExtensionScope();
       checkOtherExtensionValue(t2);
-
     }
   }
 
@@ -207,5 +205,4 @@
     double t2 = a.methodInOtherExtensionScope();
     checkOtherExtensionValue(t2);
   }
-
-}
\ No newline at end of file
+}
diff --git a/tests/language_2/extension_methods/static_extension_internal_resolution_1_test.dart b/tests/language_2/extension_methods/static_extension_internal_resolution_1_test.dart
index 9bea1cf..052ab86 100644
--- a/tests/language_2/extension_methods/static_extension_internal_resolution_1_test.dart
+++ b/tests/language_2/extension_methods/static_extension_internal_resolution_1_test.dart
@@ -72,7 +72,6 @@
       double t2 = methodInOtherExtensionScope();
       checkOtherExtensionValue(t2);
     }
-
   }
 
   void testIdentifiersOnThis() {
@@ -149,7 +148,6 @@
       self.setterInOtherExtensionScope = otherExtensionValue;
       double t2 = self.methodInOtherExtensionScope();
       checkOtherExtensionValue(t2);
-
     }
   }
 
@@ -243,5 +241,4 @@
     double t2 = a.methodInOtherExtensionScope();
     checkOtherExtensionValue(t2);
   }
-
-}
\ No newline at end of file
+}
diff --git a/tests/language_2/extension_methods/static_extension_internal_resolution_2_test.dart b/tests/language_2/extension_methods/static_extension_internal_resolution_2_test.dart
index 643581d..861bb4b 100644
--- a/tests/language_2/extension_methods/static_extension_internal_resolution_2_test.dart
+++ b/tests/language_2/extension_methods/static_extension_internal_resolution_2_test.dart
@@ -44,6 +44,7 @@
   set setterInGlobalScope(bool x) {
     Expect.equals(true, x);
   }
+
   bool methodInGlobalScope() => true;
 
   bool get fieldInInstanceScope => true;
@@ -51,6 +52,7 @@
   set setterInInstanceScope(bool x) {
     Expect.equals(true, x);
   }
+
   bool methodInInstanceScope() => true;
 
   bool get fieldInExtensionScope => true;
@@ -58,6 +60,7 @@
   set setterInExtensionScope(bool x) {
     Expect.equals(true, x);
   }
+
   bool methodInExtensionScope() => true;
 
   void testNakedIdentifiers() {
@@ -106,7 +109,6 @@
       double t2 = methodInOtherExtensionScope();
       checkOtherExtensionValue(t2);
     }
-
   }
 
   void testIdentifiersOnThis() {
@@ -214,7 +216,6 @@
   }
 }
 
-
 class B extends A {
   void testNakedIdentifiers() {
     // Globals should resolve to the global name space, and not to the members
@@ -321,5 +322,4 @@
     double t2 = a.methodInOtherExtensionScope();
     checkOtherExtensionValue(t2);
   }
-
-}
\ No newline at end of file
+}
diff --git a/tests/language_2/extension_methods/static_extension_internal_resolution_3_error_test.dart b/tests/language_2/extension_methods/static_extension_internal_resolution_3_error_test.dart
index 8803cad..8d47a88 100644
--- a/tests/language_2/extension_methods/static_extension_internal_resolution_3_error_test.dart
+++ b/tests/language_2/extension_methods/static_extension_internal_resolution_3_error_test.dart
@@ -47,6 +47,7 @@
   set setterInGlobalScope(bool x) {
     checkExtensionValue(x);
   }
+
   bool methodInGlobalScope() => extensionValue;
 
   bool get fieldInInstanceScope => extensionValue;
@@ -54,6 +55,7 @@
   set setterInInstanceScope(bool x) {
     checkExtensionValue(x);
   }
+
   bool methodInInstanceScope() => extensionValue;
 
   bool get fieldInExtensionScope => extensionValue;
@@ -61,6 +63,7 @@
   set setterInExtensionScope(bool x) {
     checkExtensionValue(x);
   }
+
   bool methodInExtensionScope() => extensionValue;
 
   void testNakedIdentifiers() {
@@ -85,7 +88,6 @@
     {
       // No errors: see static_extension_internal_resolution_3_test.dart
     }
-
   }
 
   void testIdentifiersOnThis() {
@@ -189,7 +191,6 @@
   }
 }
 
-
 class B extends A {
   void testNakedIdentifiers() {
     // Globals should resolve to the global name space, and not to the members
@@ -210,7 +211,7 @@
       // No errors: see static_extension_internal_resolution_3_test.dart
     }
 
-   // Extension members resolve to the extension methods in the other
+    // Extension members resolve to the extension methods in the other
     // extension (unresolved identifier "id" gets turned into "this.id",
     // which is then subject to extension method lookup).
     {
@@ -270,5 +271,4 @@
   {
     // No errors: see static_extension_internal_resolution_3_test.dart
   }
-
-}
\ No newline at end of file
+}
diff --git a/tests/language_2/extension_methods/static_extension_internal_resolution_3_test.dart b/tests/language_2/extension_methods/static_extension_internal_resolution_3_test.dart
index d1da8bf..f6c57e9 100644
--- a/tests/language_2/extension_methods/static_extension_internal_resolution_3_test.dart
+++ b/tests/language_2/extension_methods/static_extension_internal_resolution_3_test.dart
@@ -47,6 +47,7 @@
   set setterInGlobalScope(bool x) {
     checkExtensionValue(x);
   }
+
   bool methodInGlobalScope() => extensionValue;
 
   bool get fieldInInstanceScope => extensionValue;
@@ -54,6 +55,7 @@
   set setterInInstanceScope(bool x) {
     checkExtensionValue(x);
   }
+
   bool methodInInstanceScope() => extensionValue;
 
   bool get fieldInExtensionScope => extensionValue;
@@ -61,6 +63,7 @@
   set setterInExtensionScope(bool x) {
     checkExtensionValue(x);
   }
+
   bool methodInExtensionScope() => extensionValue;
 
   void testNakedIdentifiers() {
@@ -109,7 +112,6 @@
       double t2 = methodInOtherExtensionScope();
       checkOtherExtensionValue(t2);
     }
-
   }
 
   void testIdentifiersOnThis() {
@@ -205,7 +207,6 @@
   }
 }
 
-
 class B extends A {
   void testNakedIdentifiers() {
     // Globals should resolve to the global name space, and not to the members
@@ -305,5 +306,4 @@
     double t2 = a.methodInOtherExtensionScope();
     checkOtherExtensionValue(t2);
   }
-
-}
\ No newline at end of file
+}
diff --git a/tests/language_2/extension_methods/static_extension_internal_resolution_4_error_test.dart b/tests/language_2/extension_methods/static_extension_internal_resolution_4_error_test.dart
index 5679856..b8e80b1 100644
--- a/tests/language_2/extension_methods/static_extension_internal_resolution_4_error_test.dart
+++ b/tests/language_2/extension_methods/static_extension_internal_resolution_4_error_test.dart
@@ -47,6 +47,7 @@
   set setterInGlobalScope(bool x) {
     checkExtensionValue(x);
   }
+
   bool methodInGlobalScope() => extensionValue;
 
   bool get fieldInInstanceScope => extensionValue;
@@ -54,6 +55,7 @@
   set setterInInstanceScope(bool x) {
     checkExtensionValue(x);
   }
+
   bool methodInInstanceScope() => extensionValue;
 
   bool get fieldInExtensionScope => extensionValue;
@@ -61,6 +63,7 @@
   set setterInExtensionScope(bool x) {
     checkExtensionValue(x);
   }
+
   bool methodInExtensionScope() => extensionValue;
 
   void testNakedIdentifiers() {
@@ -85,7 +88,6 @@
     {
       // No errors: see static_extension_internal_resolution_4_test.dart
     }
-
   }
 
   void testIdentifiersOnThis() {
@@ -233,7 +235,6 @@
   }
 }
 
-
 class B extends A {
   void testNakedIdentifiers() {
     // Globals should resolve to the global name space, and not to the members
@@ -283,7 +284,7 @@
       checkExtensionValue(t2);
     }
 
-   // Extension members resolve to the extension methods in the other
+    // Extension members resolve to the extension methods in the other
     // extension (unresolved identifier "id" gets turned into "this.id",
     // which is then subject to extension method lookup).
     {
@@ -364,5 +365,4 @@
   {
     // No errors: see static_extension_internal_resolution_4_test.dart
   }
-
-}
\ No newline at end of file
+}
diff --git a/tests/language_2/extension_methods/static_extension_internal_resolution_4_test.dart b/tests/language_2/extension_methods/static_extension_internal_resolution_4_test.dart
index 3cd6f90..93955cb 100644
--- a/tests/language_2/extension_methods/static_extension_internal_resolution_4_test.dart
+++ b/tests/language_2/extension_methods/static_extension_internal_resolution_4_test.dart
@@ -47,6 +47,7 @@
   set setterInGlobalScope(bool x) {
     checkExtensionValue(x);
   }
+
   bool methodInGlobalScope() => extensionValue;
 
   bool get fieldInInstanceScope => extensionValue;
@@ -54,6 +55,7 @@
   set setterInInstanceScope(bool x) {
     checkExtensionValue(x);
   }
+
   bool methodInInstanceScope() => extensionValue;
 
   bool get fieldInExtensionScope => extensionValue;
@@ -61,6 +63,7 @@
   set setterInExtensionScope(bool x) {
     checkExtensionValue(x);
   }
+
   bool methodInExtensionScope() => extensionValue;
 
   void testNakedIdentifiers() {
@@ -109,7 +112,6 @@
       double t2 = methodInOtherExtensionScope();
       checkOtherExtensionValue(t2);
     }
-
   }
 
   void testIdentifiersOnThis() {
@@ -193,7 +195,6 @@
   }
 }
 
-
 class B extends A {
   void testNakedIdentifiers() {
     // Globals should resolve to the global name space, and not to the members
@@ -225,7 +226,7 @@
       // Error cases tested in static_extension_internal_resolution_4_error_test.dart
     }
 
-   // Extension members resolve to the extension methods in the other
+    // Extension members resolve to the extension methods in the other
     // extension (unresolved identifier "id" gets turned into "this.id",
     // which is then subject to extension method lookup).
     {
@@ -280,5 +281,4 @@
     double t2 = a.methodInOtherExtensionScope();
     checkOtherExtensionValue(t2);
   }
-
-}
\ No newline at end of file
+}
diff --git a/tests/language_2/extension_methods/static_extension_internal_resolution_5_test.dart b/tests/language_2/extension_methods/static_extension_internal_resolution_5_test.dart
index 1a567a4..0334769 100644
--- a/tests/language_2/extension_methods/static_extension_internal_resolution_5_test.dart
+++ b/tests/language_2/extension_methods/static_extension_internal_resolution_5_test.dart
@@ -28,7 +28,6 @@
 import "helpers/class_shadow.dart";
 import "helpers/class_no_shadow.dart";
 
-
 const bool extensionValue = true;
 
 void checkExtensionValue(bool x) {
@@ -41,6 +40,7 @@
 set setterInExtensionScope(int x) {
   checkGlobalValue(x);
 }
+
 int methodInExtensionScope() => globalValue;
 
 // Put the superclass members in the global scope
@@ -49,16 +49,17 @@
 set setterInInstanceScope(int x) {
   checkGlobalValue(x);
 }
+
 int methodInInstanceScope() => globalValue;
 
 // An extension which defines only its own members
 extension MyExt on AGlobal {
-
   bool get fieldInExtensionScope => extensionValue;
   bool get getterInExtensionScope => extensionValue;
   set setterInExtensionScope(bool x) {
     checkExtensionValue(x);
   }
+
   bool methodInExtensionScope() => extensionValue;
 
   bool get fieldInInstanceScope => extensionValue;
@@ -66,6 +67,7 @@
   set setterInInstanceScope(bool x) {
     checkExtensionValue(x);
   }
+
   bool methodInInstanceScope() => extensionValue;
 
   void testNakedIdentifiers() {
@@ -158,4 +160,4 @@
   var a = new AGlobal();
   a.instanceTest();
   new B().testNakedIdentifiers();
-}
\ No newline at end of file
+}
diff --git a/tests/language_2/extension_methods/static_extension_internal_resolution_6_error_test.dart b/tests/language_2/extension_methods/static_extension_internal_resolution_6_error_test.dart
index bd1ddf0..c7e3949 100644
--- a/tests/language_2/extension_methods/static_extension_internal_resolution_6_error_test.dart
+++ b/tests/language_2/extension_methods/static_extension_internal_resolution_6_error_test.dart
@@ -35,6 +35,7 @@
     //     ^^^
     // [cfe] unspecified
   }
+
   void castToShadowedTypeParam<T>() {
     dynamic s = self;
     (s as T);
@@ -46,7 +47,6 @@
   }
 }
 
-
 const bool extensionValue = true;
 
 void checkExtensionValue(bool x) {
@@ -62,10 +62,11 @@
   //              ^^^^^^^^^^^^^^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.EXTENSION_CONFLICTING_STATIC_AND_INSTANCE
   static set setterInInstanceScope(bool x) {
-  //         ^^^^^^^^^^^^^^^^^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.EXTENSION_CONFLICTING_STATIC_AND_INSTANCE
+    //       ^^^^^^^^^^^^^^^^^^^^^
+    // [analyzer] COMPILE_TIME_ERROR.EXTENSION_CONFLICTING_STATIC_AND_INSTANCE
     checkExtensionValue(x);
   }
+
   static bool methodInInstanceScope() => extensionValue;
   //          ^^^^^^^^^^^^^^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.EXTENSION_CONFLICTING_STATIC_AND_INSTANCE
@@ -76,6 +77,7 @@
   static set setterInGlobalScope(bool x) {
     checkExtensionValue(x);
   }
+
   static bool methodInGlobalScope() => extensionValue;
 
   // Invalid to overlap the static and extension scopes
@@ -86,15 +88,15 @@
   //       ^^^
   // [cfe] unspecified
   set setterInInstanceScope(bool x) {
-  //  ^^^
-  // [cfe] unspecified
+    //^^^
+    // [cfe] unspecified
     checkExtensionValue(x);
   }
+
   bool methodInInstanceScope() => extensionValue;
   //   ^^^
   // [cfe] unspecified
 
-
   void testNakedIdentifiers() {
     // Symbols in the global scope and the local static scope resolve to
     // the local static scope.
@@ -108,6 +110,7 @@
       // No errors: see static_extension_internal_resolution_6_test.dart
     }
   }
+
   void instanceTest() {
     StaticExt(this).testNakedIdentifiers();
   }
@@ -119,4 +122,4 @@
 
   Expect.throwsCastError(() => 3.castToShadowedTypeParam<String>());
   Expect.throwsCastError(() => 3.castToShadowedTypeList<String>());
-}
\ No newline at end of file
+}
diff --git a/tests/language_2/extension_methods/static_extension_internal_resolution_6_test.dart b/tests/language_2/extension_methods/static_extension_internal_resolution_6_test.dart
index 9c63c3b..929b306 100644
--- a/tests/language_2/extension_methods/static_extension_internal_resolution_6_test.dart
+++ b/tests/language_2/extension_methods/static_extension_internal_resolution_6_test.dart
@@ -37,7 +37,6 @@
   }
 }
 
-
 const bool extensionValue = true;
 
 void checkExtensionValue(bool x) {
@@ -51,6 +50,7 @@
   static set setterInInstanceScope(bool x) {
     checkExtensionValue(x);
   }
+
   static bool methodInInstanceScope() => extensionValue;
 
   // Add the global symbols
@@ -59,6 +59,7 @@
   static set setterInGlobalScope(bool x) {
     checkExtensionValue(x);
   }
+
   static bool methodInGlobalScope() => extensionValue;
 
   void testNakedIdentifiers() {
@@ -86,6 +87,7 @@
       checkExtensionValue(t2);
     }
   }
+
   void instanceTest() {
     StaticExt(this).testNakedIdentifiers();
   }
@@ -96,4 +98,4 @@
   a.instanceTest();
 
   Expect.throwsCastError(() => 3.castToShadowedTypeParam<String>());
-}
\ No newline at end of file
+}
diff --git a/tests/language_2/extension_methods/static_extension_operators_test.dart b/tests/language_2/extension_methods/static_extension_operators_test.dart
index ebada0d..6f902c8 100644
--- a/tests/language_2/extension_methods/static_extension_operators_test.dart
+++ b/tests/language_2/extension_methods/static_extension_operators_test.dart
@@ -75,7 +75,7 @@
   expect("a[b]", a[b]--, "a[b]=(a[b]-1)");
 
   // Combinations.
-  expect("(a+b[b(c)](a*b))", a + b[c[a] = b(c)](a * b), "c[a]=b(c)");
+  expect("(a+b[b(c)]((a*b)))", a + b[c[a] = b(c)](a * b), "c[a]=b(c)");
 
   // Operator precedence is unaffected by being extensions.
   expect("(c<((-a)|(b^((~c)&((a<<b)>>((c-a)+((((b*c)~/a)%b)/c)))))))",
diff --git a/tests/language_2/extension_methods/static_extension_setter_getter_assignability_error_test.dart b/tests/language_2/extension_methods/static_extension_setter_getter_assignability_error_test.dart
index e5005da..1cff35a 100644
--- a/tests/language_2/extension_methods/static_extension_setter_getter_assignability_error_test.dart
+++ b/tests/language_2/extension_methods/static_extension_setter_getter_assignability_error_test.dart
@@ -26,4 +26,4 @@
   // [cfe] unspecified
 }
 
-void main() {}
\ No newline at end of file
+void main() {}
diff --git a/tests/language_2/extension_methods/static_extension_silly_types_test.dart b/tests/language_2/extension_methods/static_extension_silly_types_test.dart
index 3b13f19..6f69e79 100644
--- a/tests/language_2/extension_methods/static_extension_silly_types_test.dart
+++ b/tests/language_2/extension_methods/static_extension_silly_types_test.dart
@@ -77,7 +77,6 @@
 
 class C = Object with M;
 
-
 extension on M {
   int get m => 1;
 }
@@ -87,8 +86,8 @@
   testVoid() {
     // No access on void. Static type of `this` is void!
     this //
-      .toString() //# 01: compile-time error
-    ;
+            .toString() //# 01: compile-time error
+        ;
   }
 }
 
diff --git a/tests/language_2/extension_methods/static_extension_syntax_test.dart b/tests/language_2/extension_methods/static_extension_syntax_test.dart
index 1ab928a..0d71b60 100644
--- a/tests/language_2/extension_methods/static_extension_syntax_test.dart
+++ b/tests/language_2/extension_methods/static_extension_syntax_test.dart
@@ -141,7 +141,7 @@
   List<T> get list17 => <T>[];
 }
 
-extension <T extends Rec<T>> on T {
+extension<T extends Rec<T>> on T {
   int get e19 => 19;
   List<T> get list19 => <T>[];
 }
diff --git a/tests/language_2/external_test.dart b/tests/language_2/external_test.dart
index 9901999..c021505 100644
--- a/tests/language_2/external_test.dart
+++ b/tests/language_2/external_test.dart
@@ -16,18 +16,15 @@
   external var x01; // //# 01: syntax error
   external int x02; // //# 02: syntax error
 
-  external f10(); //  //# 10: runtime error
   external f11() { } // //# 11: syntax error
   external f12() => 1; // //# 12: syntax error
-  external static f13(); // //# 13: runtime error
   static external f14(); // //# 14: syntax error
   int external f16(); // //# 16: syntax error
 
-  external Foo.n20(val); // //# 20: runtime error
-  external Foo.n21(val) : x = 1; // //# 21: runtime error
+  external Foo.n21(val) : x = 1; // //# 21: syntax error
   external Foo.n22(val) { x = 1; } // //# 22: syntax error
   external factory Foo.n23(val) => new Foo(); // //# 23: syntax error
-  external Foo.n24(this.x); // //# 24: runtime error
+  external Foo.n24(this.x); // //# 24: compile-time error
   external factory Foo.n25(val) = Bar; // //# 25: syntax error
 }
 
@@ -38,16 +35,11 @@
   // Ensure Foo class is compiled.
   var foo = new Foo();
 
-  // Try calling an unpatched external function.
-  new Foo().f10(); //                                   //# 10: continued
   new Foo().f11(); //                                   //# 11: continued
   new Foo().f12(); //                                   //# 12: continued
-  Foo.f13(); //                                         //# 13: continued
   Foo.f14(); //                                         //# 14: continued
   new Foo().f16(); //                                   //# 16: continued
 
-  // Try calling an unpatched external constructor.
-  new Foo.n20(1); //                                     //# 20: continued
   new Foo.n21(1); //                                     //# 21: continued
   new Foo.n22(1); //                                     //# 22: continued
   new Foo.n23(1); //                                     //# 23: continued
diff --git a/tests/language_2/flatten_test.dart b/tests/language_2/flatten_test.dart
index 618c0b6..2ff13e9 100644
--- a/tests/language_2/flatten_test.dart
+++ b/tests/language_2/flatten_test.dart
@@ -12,13 +12,9 @@
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
 
-// TODO(vsm): Restore when https://github.com/dart-lang/sdk/issues/25611
-// is fixed.
-/*
 class Divergent<T> implements Future<Divergent<Divergent<T>>> {
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
-*/
 
 test() async {
   // flatten(Derived<int>) = int
@@ -27,9 +23,6 @@
   Future<int> f() async { return new Derived<int>(); } //# 03: ok
   Future<int> x = (() async => new Derived<int>())(); //# 04: runtime error
 
-  // TODO(vsm): Restore when https://github.com/dart-lang/sdk/issues/25611
-  // is fixed.
-  /*
   // flatten(FixedPoint<int>) = FixedPoint<int>
   FixedPoint<int> x = await new FixedPoint<int>(); //# 05: runtime error
   Future<FixedPoint<int>> f() async => new FixedPoint<int>(); //# 06: ok
@@ -41,7 +34,6 @@
   Future<Divergent<Divergent<int>>> f() async => new Divergent<int>(); //# 10: ok
   Future<Divergent<Divergent<int>>> f() async { return new Divergent<int>(); } //# 11: ok
   Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())(); //# 12: runtime error
-  */
 }
 
 main() {
diff --git a/tests/language_2/generic_mock_test.dart b/tests/language_2/generic_mock_test.dart
new file mode 100644
index 0000000..f30e43e
--- /dev/null
+++ b/tests/language_2/generic_mock_test.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.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/38384
+
+class Built<X, Y> {}
+
+class Foo {
+  foo<S extends Built<S, B>, B extends Built<S, B>>() {}
+}
+
+class Mock {
+  noSuchMethod(Invocation i) {}
+}
+
+class MockFoo extends Mock implements Foo {}
+
+main() {}
diff --git a/tests/language_2/generic_no_such_method_dispatcher_simple_test.dart b/tests/language_2/generic_no_such_method_dispatcher_simple_test.dart
deleted file mode 100644
index a829f56..0000000
--- a/tests/language_2/generic_no_such_method_dispatcher_simple_test.dart
+++ /dev/null
@@ -1,32 +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.
-// VMOptions=--reify-generic-functions --optimization-counter-threshold=10 --no-use-osr --no-background-compilation
-
-library generic_no_such_method_dispatcher_test_simple;
-
-import "package:expect/expect.dart";
-
-// A simple test that noSuchMethod dispatching works correctly with generic
-// functions. We will remove this once the more complex version of this test
-// 'generic_no_such_method_dispatcher_test' can be compiled by Fasta.
-
-class A {}
-
-class B extends A {
-  foo() => super.foo<int>();
-}
-
-test(fn) {
-  try {
-    fn();
-  } catch (e) {
-    Expect.isTrue(e.toString().contains("foo<int>"));
-  }
-}
-
-main() {
-  test(() => (new B()).foo()); // missing generic super call
-  test(() => foo<int>()); // missing generic static call
-  test(() => (new A()).foo<int>()); // missing generic method call
-}
diff --git a/tests/language_2/language_2.status b/tests/language_2/language_2.status
index d03e859..9e9b7a4 100644
--- a/tests/language_2/language_2.status
+++ b/tests/language_2/language_2.status
@@ -53,12 +53,6 @@
 partial_instantiation_static_bounds_check_test/02: MissingCompileTimeError # Issue 34327
 partial_instantiation_static_bounds_check_test/03: MissingCompileTimeError # Issue 34327
 
-[ $compiler != compare_analyzer_cfe && $compiler != spec_parser ]
-mixin_constructor_forwarding/const_constructor_test/none: CompileTimeError # Issue 32223
-mixin_constructor_forwarding/const_constructor_with_field_test/none: CompileTimeError # Issue 32223
-mixin_constructor_forwarding/optional_named_parameters_test/none: CompileTimeError # Issue 31543
-mixin_constructor_forwarding/optional_positional_parameters_test/none: CompileTimeError # Issue 31543
-
 [ $compiler != dart2js && $compiler != dartdevc && !$checked ]
 function_type/*: Skip # Needs checked mode.
 
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status
index cddcbd3..372d94b 100644
--- a/tests/language_2/language_2_analyzer.status
+++ b/tests/language_2/language_2_analyzer.status
@@ -5,7 +5,6 @@
 # Sections in this file should contain "$compiler == dart2analyzer".
 
 [ $compiler == dart2analyzer ]
-generic_no_such_method_dispatcher_simple_test: Skip # failing-by-design: This test is just for kernel
 large_class_declaration_test: Slow
 vm/debug_break_enabled_vm_test: Skip
 vm/debug_break_vm_test/*: Skip
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 2478e07..fb8135f 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -14,8 +14,6 @@
 call_method_must_not_be_getter_test/03: RuntimeError # Issue 32155
 canonical_const2_test: RuntimeError, OK # non JS number semantics
 closure_type_arguments_test: Crash # Issue 34272
-config_import_corelib_test: CompileTimeError # we need a special platform.dill file for categories=all. Once we fix that, all dart:* are supported when using '--categories=all' so this will become a RuntimeError, OK.
-config_import_test: RuntimeError # Test flag is not passed to the compiler.
 const_constructor3_test/04: MissingCompileTimeError # OK - Subtype check uses JS number semantics.
 const_dynamic_type_literal_test/03: Pass # but it shouldn't until we fix issue 17207
 const_switch_test/02: RuntimeError, OK # constant identity based on JS constants
@@ -27,9 +25,6 @@
 double_identical_test: RuntimeError # Negative and positive zero are distinct, but not in dart2js; bug #11551.
 double_int_to_string_test: RuntimeError, OK # non JS number semantics
 expect_test: RuntimeError, OK # Issue 13080
-external_test/10: CompileTimeError # External non-js-interop function are treated as compile-time errors.
-external_test/13: CompileTimeError # External non-js-interop function are treated as compile-time errors.
-external_test/20: CompileTimeError # External non-js-interop function are treated as compile-time errors.
 full_stacktrace1_test: RuntimeError # Issue 12698
 full_stacktrace2_test: RuntimeError # Issue 12698
 full_stacktrace3_test: RuntimeError # Issue 12698
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index 9afe4d1..4abcf1c 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -9,7 +9,6 @@
 const_double_in_int_op_test/id6: Skip # Triple shift
 const_double_in_int_op_test/ii6: Skip # Triple shift
 extension_methods/*: SkipByDesign # Analyzer DDC is expected to be turned down before releasing extension methods.
-generic_no_such_method_dispatcher_simple_test: Skip # This test is just for kernel.
 large_class_declaration_test: Slow
 nnbd/*: Skip
 
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index 0f1d7ea..9b43134 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -52,7 +52,6 @@
 inference_enum_list_test: Skip # Issue 35885
 
 [ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled ]
-external_test/13: Crash
 vm/precompiled_static_initializer_test: Slow
 
 # ==== dartkp + dart_precompiled status lines ====
diff --git a/tests/language_2/language_2_precompiled.status b/tests/language_2/language_2_precompiled.status
index 4149ec3..f89d8f4 100644
--- a/tests/language_2/language_2_precompiled.status
+++ b/tests/language_2/language_2_precompiled.status
@@ -23,8 +23,6 @@
 enum_duplicate_test/*: Skip # Uses Enum.toString()
 enum_private_test/*: Skip # Uses Enum.toString()
 enum_test: Skip # Uses Enum.toString()
-f_bounded_quantification4_test: Skip
-f_bounded_quantification5_test: Skip
 full_stacktrace1_test: Skip
 full_stacktrace2_test: Skip
 full_stacktrace3_test: Skip
diff --git a/tests/language_2/language_2_spec_parser.status b/tests/language_2/language_2_spec_parser.status
index 28ae988..171c316 100644
--- a/tests/language_2/language_2_spec_parser.status
+++ b/tests/language_2/language_2_spec_parser.status
@@ -7,14 +7,11 @@
 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.
-config_import_corelib_test: Fail # Uses conditional import.
-config_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.
-external_test/21: Fail # Test expects `runtime error`, it is a syntax error.
 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.
diff --git a/tests/language_2/mixin_constructor_forwarding/const_constructor_test.dart b/tests/language_2/mixin_constructor_forwarding/const_constructor_test.dart
index aa59e5e..ba57bdf 100644
--- a/tests/language_2/mixin_constructor_forwarding/const_constructor_test.dart
+++ b/tests/language_2/mixin_constructor_forwarding/const_constructor_test.dart
@@ -40,8 +40,6 @@
 
 class Application = Base with Mixin;
 
-class Application2 extends Base with Mixin {}
-
 main() {
   Expect.equals(42, new Application.c1(42).m);
   Expect.equals(42, new Application.c2(42).m);
@@ -59,53 +57,22 @@
   Expect.equals(42, const Application.c14(42).m);
   Expect.equals(42, const Application.c15(x: 42).m);
 
-  Expect.equals(37, new Application.c2().m);
+  Expect.equals(37, new Application.c2().m); //# issue38304: ok
   Expect.equals(37, new Application.c3().m);
-  Expect.equals(37, const Application.c5().m);
+  Expect.equals(37, const Application.c5().m); //# issue38304: continued
   Expect.equals(37, const Application.c6().m);
-  Expect.equals(87, const Application.c8().m);
+  Expect.equals(87, const Application.c8().m); //# issue38304: continued
   Expect.equals(87, const Application.c9().m);
-  Expect.equals(87, const Application.c11().m);
+  Expect.equals(87, const Application.c11().m); //# issue38304: continued
   Expect.equals(87, const Application.c12().m);
-  Expect.equals(87, const Application.c14().m);
+  Expect.equals(87, const Application.c14().m); //# issue38304: continued
   Expect.equals(87, const Application.c15().m);
 
-  Expect.equals(42, new Application2.c1(42).m);
-  Expect.equals(42, new Application2.c2(42).m);
-  Expect.equals(42, new Application2.c3(x: 42).m);
-  Expect.equals(42, const Application2.c4(42).m);
-  Expect.equals(42, const Application2.c5(42).m);
-  Expect.equals(42, const Application2.c6(x: 42).m);
-  Expect.equals(42, const Application2.c7(42).m);
-  Expect.equals(42, const Application2.c8(42).m);
-  Expect.equals(42, const Application2.c9(x: 42).m);
-  Expect.equals(42, const Application2.c10(42).m);
-  Expect.equals(42, const Application2.c11(42).m);
-  Expect.equals(42, const Application2.c12(x: 42).m);
-  Expect.equals(42, const Application2.c13(42).m);
-  Expect.equals(42, const Application2.c14(42).m);
-  Expect.equals(42, const Application2.c15(x: 42).m);
-
-  Expect.equals(37, new Application2.c2().m);
-  Expect.equals(37, new Application2.c3().m);
-  Expect.equals(37, const Application2.c5().m);
-  Expect.equals(37, const Application2.c6().m);
-  Expect.equals(87, const Application2.c8().m);
-  Expect.equals(87, const Application2.c9().m);
-  Expect.equals(87, const Application2.c11().m);
-  Expect.equals(87, const Application2.c12().m);
-  Expect.equals(87, const Application2.c14().m);
-  Expect.equals(87, const Application2.c15().m);
-
   // Only make forwarders const if original constructor is const.
   const Application.c1(0); //# 01: compile-time error
   const Application.c2(0); //# 02: compile-time error
   const Application.c3(x: 0); //# 03: compile-time error
-  const Application2.c1(0); //# 04: compile-time error
-  const Application2.c2(0); //# 05: compile-time error
-  const Application2.c3(x: 0); //# 06: compile-time error
 
   // Only insert forwarders for generative constructors.
-  new Application(); //# 07: compile-time error
-  new Application2(); //# 08: compile-time error
+  new Application(); //# 04: compile-time error
 }
diff --git a/tests/language_2/mixin_constructor_forwarding/const_constructor_with_field_test.dart b/tests/language_2/mixin_constructor_forwarding/const_constructor_with_field_test.dart
index ee9bad7..e22be63 100644
--- a/tests/language_2/mixin_constructor_forwarding/const_constructor_with_field_test.dart
+++ b/tests/language_2/mixin_constructor_forwarding/const_constructor_with_field_test.dart
@@ -44,8 +44,6 @@
 
 class Application = Base with Mixin;
 
-class Application2 extends Base with Mixin {}
-
 main() {
   Expect.equals(42, new Application.c1(42).m);
   Expect.equals(42, new Application.c2(42).m);
@@ -63,44 +61,17 @@
   Expect.equals(42, new Application.c14(42).m);
   Expect.equals(42, new Application.c15(x: 42).m);
 
-  Expect.equals(37, new Application.c2().m);
+  Expect.equals(37, new Application.c2().m); //# issue38304: ok
   Expect.equals(37, new Application.c3().m);
-  Expect.equals(37, new Application.c5().m);
+  Expect.equals(37, new Application.c5().m); //# issue38304: continued
   Expect.equals(37, new Application.c6().m);
-  Expect.equals(87, new Application.c8().m);
+  Expect.equals(87, new Application.c8().m); //# issue38304: continued
   Expect.equals(87, new Application.c9().m);
-  Expect.equals(87, new Application.c11().m);
+  Expect.equals(87, new Application.c11().m); //# issue38304: continued
   Expect.equals(87, new Application.c12().m);
-  Expect.equals(87, new Application.c14().m);
+  Expect.equals(87, new Application.c14().m); //# issue38304: continued
   Expect.equals(87, new Application.c15().m);
 
-  Expect.equals(42, new Application2.c1(42).m);
-  Expect.equals(42, new Application2.c2(42).m);
-  Expect.equals(42, new Application2.c3(x: 42).m);
-  Expect.equals(42, new Application2.c4(42).m);
-  Expect.equals(42, new Application2.c5(42).m);
-  Expect.equals(42, new Application2.c6(x: 42).m);
-  Expect.equals(42, new Application2.c7(42).m);
-  Expect.equals(42, new Application2.c8(42).m);
-  Expect.equals(42, new Application2.c9(x: 42).m);
-  Expect.equals(42, new Application2.c10(42).m);
-  Expect.equals(42, new Application2.c11(42).m);
-  Expect.equals(42, new Application2.c12(x: 42).m);
-  Expect.equals(42, new Application2.c13(42).m);
-  Expect.equals(42, new Application2.c14(42).m);
-  Expect.equals(42, new Application2.c15(x: 42).m);
-
-  Expect.equals(37, new Application2.c2().m);
-  Expect.equals(37, new Application2.c3().m);
-  Expect.equals(37, new Application2.c5().m);
-  Expect.equals(37, new Application2.c6().m);
-  Expect.equals(87, new Application2.c8().m);
-  Expect.equals(87, new Application2.c9().m);
-  Expect.equals(87, new Application2.c11().m);
-  Expect.equals(87, new Application2.c12().m);
-  Expect.equals(87, new Application2.c14().m);
-  Expect.equals(87, new Application2.c15().m);
-
   // Don't make constructors const if mixin declares instance variable.
   const Application.c4(42); //# 00: compile-time error
   const Application.c5(42); //# 01: compile-time error
@@ -115,20 +86,6 @@
   const Application.c14(42); //# 10: compile-time error
   const Application.c15(x: 42); //# 11: compile-time error
 
-  const Application2.c4(42); //# 12: compile-time error
-  const Application2.c5(42); //# 13: compile-time error
-  const Application2.c6(x: 42); //# 14: compile-time error
-  const Application2.c7(42); //# 15: compile-time error
-  const Application2.c8(42); //# 16: compile-time error
-  const Application2.c9(x: 42); //# 17: compile-time error
-  const Application2.c10(42); //# 18: compile-time error
-  const Application2.c11(42); //# 19: compile-time error
-  const Application2.c12(x: 42); //# 20: compile-time error
-  const Application2.c13(42); //# 21: compile-time error
-  const Application2.c14(42); //# 22: compile-time error
-  const Application2.c15(x: 42); //# 23: compile-time error
-
   // Only insert forwarders for generative constructors.
-  new Application(); //# 24: compile-time error
-  new Application2(); //# 25: compile-time error
+  new Application(); //# 12: compile-time error
 }
diff --git a/tests/language_2/mixin_constructor_forwarding/optional_named_parameters_test.dart b/tests/language_2/mixin_constructor_forwarding/optional_named_parameters_test.dart
index e4b7c58..8cab4c5 100644
--- a/tests/language_2/mixin_constructor_forwarding/optional_named_parameters_test.dart
+++ b/tests/language_2/mixin_constructor_forwarding/optional_named_parameters_test.dart
@@ -22,8 +22,6 @@
 
 class Application = Base with Mixin;
 
-class Application2 extends Base with Mixin {}
-
 main() {
   Expect.equals(42, new Application.c1(42).m);
   Expect.equals(42, new Application.c2(x: 42).m);
@@ -35,17 +33,6 @@
   Expect.equals(37, new Application.c4().m);
   Expect.equals(37, new Application.c6().m);
 
-  Expect.equals(42, new Application2.c1(42).m);
-  Expect.equals(42, new Application2.c2(x: 42).m);
-  Expect.equals(42, new Application2.c3(42).m);
-  Expect.equals(42, new Application2.c4(x: 42).m);
-  Expect.equals(42, new Application2.c5(42).m);
-  Expect.equals(42, new Application2.c6(x: 42).m);
-  Expect.equals(37, new Application2.c2().m);
-  Expect.equals(37, new Application2.c4().m);
-  Expect.equals(37, new Application2.c6().m);
-
   // Only insert forwarders for generative constructors.
   new Application(); //# 01: compile-time error
-  new Application2(); //# 02: compile-time error
 }
diff --git a/tests/language_2/mixin_constructor_forwarding/optional_positional_parameters_test.dart b/tests/language_2/mixin_constructor_forwarding/optional_positional_parameters_test.dart
index cf84a97..1411223 100644
--- a/tests/language_2/mixin_constructor_forwarding/optional_positional_parameters_test.dart
+++ b/tests/language_2/mixin_constructor_forwarding/optional_positional_parameters_test.dart
@@ -22,8 +22,6 @@
 
 class Application = Base with Mixin;
 
-class Application2 extends Base with Mixin {}
-
 main() {
   Expect.equals(42, new Application.c1(42).m);
   Expect.equals(42, new Application.c2(42).m);
@@ -35,17 +33,6 @@
   Expect.equals(37, new Application.c4().m);
   Expect.equals(37, new Application.c6().m);
 
-  Expect.equals(42, new Application2.c1(42).m);
-  Expect.equals(42, new Application2.c2(42).m);
-  Expect.equals(42, new Application2.c3(42).m);
-  Expect.equals(42, new Application2.c4(42).m);
-  Expect.equals(42, new Application2.c5(42).m);
-  Expect.equals(42, new Application2.c6(42).m);
-  Expect.equals(37, new Application2.c2().m);
-  Expect.equals(37, new Application2.c4().m);
-  Expect.equals(37, new Application2.c6().m);
-
   // Only insert forwarders for generative constructors.
   new Application(); //# 01: compile-time error
-  new Application2(); //# 02: compile-time error
 }
diff --git a/tests/language_2/override_const_field_test.dart b/tests/language_2/override_const_field_test.dart
new file mode 100644
index 0000000..8018296
--- /dev/null
+++ b/tests/language_2/override_const_field_test.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.
+// Dart test checking that static/instance field shadowing do not conflict.
+
+import 'package:expect/expect.dart';
+
+class A {
+  final field;
+  const A(this.field);
+}
+
+class B extends A {
+  final field;
+  const B(this.field, fieldA) : super(fieldA);
+  get fieldA => super.field;
+}
+
+main() {
+  const b = B(1, 2);
+  Expect.equals(1, b.field);
+  Expect.equals(2, b.fieldA);
+}
diff --git a/tests/language_2/setter_no_getter_test.dart b/tests/language_2/setter_no_getter_test.dart
index c6371c1..756ccb0 100644
--- a/tests/language_2/setter_no_getter_test.dart
+++ b/tests/language_2/setter_no_getter_test.dart
@@ -2,13 +2,21 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import "package:expect/expect.dart";
-
-/* //   //# 01: runtime error
-get topLevel => 42;
-*/ //  //# 01: continued
 set topLevel(var value) {}
 
+class Example {
+  set foo(var value) {}
+}
+
 main() {
-  Expect.equals(42, topLevel++); //# 01: continued
+  print(topLevel++);
+  //    ^
+  // [analyzer] unspecified
+  // [cfe] Getter not found: 'topLevel'.
+
+  Example ex = new Example();
+  print(ex.foo++);
+  //       ^
+  // [analyzer] unspecified
+  // [cfe] The getter 'foo' isn't defined for the class 'Example'.
 }
diff --git a/tests/language_2/super_call4_test.dart b/tests/language_2/super_call4_test.dart
index dbff2ea..aced9d7 100644
--- a/tests/language_2/super_call4_test.dart
+++ b/tests/language_2/super_call4_test.dart
@@ -4,12 +4,7 @@
 
 import "package:expect/expect.dart";
 
-// Checks that noSuchMethod is resolved in the super class and not in the
-// current class.
-
 class C {
-  E e = new E();
-
   bool foo();
   bool bar(int a);
   bool baz({int b});
@@ -21,34 +16,30 @@
 class D extends C {
   bool noSuchMethod(Invocation im) => false;
 
+  // `super.foo()` et al. will statically use [C]'s [noSuchMethod] forwarder,
+  // but the forwarder will (virtually) call [D]'s [noSuchMethod] at runtime.
+
   test1() {
-    return super.foo(); //# 01: compile-time error
+    return super.foo();
   }
 
   test2() {
-    return super.bar(1); //# 01: compile-time error
+    return super.bar(1);
   }
 
   test3() {
-    return super.baz(b: 2); //# 01: compile-time error
+    return super.baz(b: 2);
   }
 
   test4() {
-    return super.boz(1, c: 2); //# 01: compile-time error
+    return super.boz(1, c: 2);
   }
 }
 
-class E {
-  bool foo() => true;
-  bool bar(int a) => a == 1;
-  bool baz({int b}) => b == 2;
-  bool boz(int a, {int c}) => a == 1 && c == 2;
-}
-
 main() {
   var d = new D();
-  Expect.isNull(d.test1());
-  Expect.isNull(d.test2());
-  Expect.isNull(d.test3());
-  Expect.isNull(d.test4());
+  Expect.isFalse(d.test1());
+  Expect.isFalse(d.test2());
+  Expect.isFalse(d.test3());
+  Expect.isFalse(d.test4());
 }
diff --git a/tests/language_2/syntax_test.dart b/tests/language_2/syntax_test.dart
index 5946a1d..107e022 100644
--- a/tests/language_2/syntax_test.dart
+++ b/tests/language_2/syntax_test.dart
@@ -232,8 +232,8 @@
     G<> t; //# 57: syntax error
     G<null> t; //# 58: syntax error
     A<void> a = null; //# 59: compile-time error
-    void v; //# 60: compile-time error
-    void v = null; //# 61: compile-time error
+    void v; //# 60: ok
+    void v = null; //# 61: ok
     print(null is void); //# 62: syntax error
     new A();
     new B();
diff --git a/tests/language_2/type_variable_bound_access_test.dart b/tests/language_2/type_variable_bound_access_test.dart
new file mode 100644
index 0000000..019a75f
--- /dev/null
+++ b/tests/language_2/type_variable_bound_access_test.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 DynamicClass<T extends dynamic, S extends T> {
+  T field1;
+  T field2;
+
+  DynamicClass(this.field1, this.field2);
+
+  method() => field1 * field2;
+}
+
+class NumClass<T extends num, S extends T> {
+  T field1;
+  S field2;
+
+  NumClass(this.field1, this.field2);
+
+  num method1() => field1 * field2;
+
+  num method2() => field1 + field2.length; //# 01: compile-time error
+}
+
+main() {
+  new DynamicClass<num, int>(0.5, 2).method();
+  new NumClass<num, double>(2, 0.5).method1();
+  new NumClass<num, double>(2, 0.5).method2(); //# 01: continued
+}
diff --git a/tests/language_2/variance/syntax/variance_disabled_syntax_test.dart b/tests/language_2/variance/syntax/variance_disabled_syntax_test.dart
new file mode 100644
index 0000000..9230532
--- /dev/null
+++ b/tests/language_2/variance/syntax/variance_disabled_syntax_test.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.
+
+// Tests that since `variance` flag is disabled, correct variance modifier usage will issue an error.
+
+class A<in X> {}
+//      ^^
+// [analyzer] COMPILE_TIME_ERROR.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME
+// [cfe] Expected an identifier, but got 'in'.
+//      ^^
+// [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+//         ^
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+// [cfe] Expected ',' before this.
+
+class B<out X, in Y, inout Z> {}
+//          ^
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+// [cfe] Expected ',' before this.
+//             ^^
+// [analyzer] COMPILE_TIME_ERROR.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME
+// [cfe] Expected an identifier, but got 'in'.
+//             ^^
+// [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+//                ^
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+// [cfe] Expected ',' before this.
+//                         ^
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+// [cfe] Expected ',' before this.
+
+mixin C<inout T> {}
+//            ^
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+// [cfe] Expected ',' before this.
+
+typedef D<out T> = T Function();
+//            ^
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+// [cfe] Expected ',' before this.
diff --git a/tests/language_2/variance/syntax/variance_keyword_identifier_syntax_test.dart b/tests/language_2/variance/syntax/variance_keyword_identifier_syntax_test.dart
new file mode 100644
index 0000000..5028b51
--- /dev/null
+++ b/tests/language_2/variance/syntax/variance_keyword_identifier_syntax_test.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.
+
+// Tests identifier usage of keywords `out` and `inout`, correct usage of `in`.
+
+import "package:expect/expect.dart";
+
+class OutParameter {
+  var out = 3;
+  int func(int out) {
+    return out;
+  }
+}
+
+class inout {
+  void out(int x) {}
+}
+
+var out = 5;
+
+main() {
+  OutParameter x = new OutParameter();
+  Expect.equals(2, x.func(2));
+  Expect.equals(3, x.out);
+
+  inout foo = inout();
+  foo.out(4);
+
+  Expect.equals(5, out);
+
+  var collection = [0, 1, 2];
+  for (var x in collection) {
+    Expect.isTrue(x is int);
+  }
+}
diff --git a/tests/language_2/vm/regression_38231_test.dart b/tests/language_2/vm/regression_38231_test.dart
new file mode 100644
index 0000000..a269d67
--- /dev/null
+++ b/tests/language_2/vm/regression_38231_test.dart
@@ -0,0 +1,126 @@
+// 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=1
+
+import "package:expect/expect.dart";
+
+import 'dart:typed_data';
+
+// Found by DartFuzzing: would sometimes crash on OSR
+// https://github.com/dart-lang/sdk/issues/38231
+
+import 'dart:async';
+import 'dart:cli';
+import 'dart:collection';
+import 'dart:convert';
+import 'dart:core';
+import 'dart:io';
+import 'dart:isolate';
+import 'dart:math';
+import 'dart:typed_data';
+
+Map<int, String> var0 = {
+  41: 'V\u2665Y\u2665#Xs',
+  for (int loc0 in {
+    if (true) for (int loc0 in {-2147483649}) -4294967167 else if (false) -1,
+    -60,
+    -82,
+    -21,
+    for (int loc0 in [
+      -9223372036854771712,
+      for (int loc0 = 0; loc0 < 53; loc0++) 96
+    ])
+      1,
+    -58,
+    77
+  })
+    95: '',
+  5: 'z2\u2665e',
+  if (false) for (int loc0 in [-87, -2147483649, 0, 97, -53, 95]) 10: '#synP3',
+  22: ''
+};
+String var1 = ')LIpwG';
+double var2 = 0.30016980633333135;
+bool var3 = true;
+bool var4 = true;
+int var5 = -9223372036854774808;
+double var6 = 0.7012235530406754;
+String var7 = 'H';
+List<int> var8 = [90, -50, -34, -97, -33, 1];
+Set<int> var9 = {
+  42,
+  36,
+  9223372034707292159,
+  ...{52},
+  97,
+  for (int loc0 in {
+    if (true) ...{13} else -54,
+    -26,
+    -38,
+    9223372032559808513,
+    60
+  })
+    for (int loc1 in {
+      for (int loc1 in {19, 60}) -4294967280,
+      -17,
+      -62
+    }) ...{23, 11},
+  for (int loc0 = 0; loc0 < 30; loc0++) -44
+};
+Map<int, String> var10 = {
+  for (int loc0 in {
+    ...{
+      -52,
+      -9223372030412324864,
+      if (true) 82,
+      ...{76, 5, 9223372032559841279, 98, 58, 97, -127, 72},
+      for (int loc0 in [-97]) -14,
+      for (int loc0 = 0; loc0 < 21; loc0++) 88
+    },
+    -52,
+    for (int loc0 = 0; loc0 < 63; loc0++) ...{64, 0},
+    for (int loc0 = 0; loc0 < 67; loc0++) ...{67}
+  })
+    54: '',
+  41: 'cvokV0',
+  4: '9\u2665',
+  35: 'vRkv',
+  41: '\u2665',
+  63: 'Nu+u\u26659S'
+};
+
+class X0 {}
+
+class X1 with X0 {
+  bool foo1_0(List<int> par1, bool par2) => true;
+  Map<int, String> foo1_1(Set<int> par1, bool par2, Set<int> par3) {
+    return {1: "a", 2: "b"};
+  }
+}
+
+main() {
+  try {
+    X1().foo1_0([1, 2], true);
+  } catch (exception, stackTrace) {
+    print('X1().foo1_0() throws');
+  }
+  try {
+    X1().foo1_1(
+        {
+          32,
+          -94,
+          -2147483649,
+          -43,
+          for (int loc0 in {56, -31}) -9223372032559775745,
+          53,
+          86,
+          4294967296
+        },
+        var4,
+        {1, 2});
+  } catch (exception, stackTrace) {
+    print('X1().foo1_1() throws');
+  }
+}
diff --git a/tests/lib_2/async/stream_distinct_test.dart b/tests/lib_2/async/stream_distinct_test.dart
index bc642d4..354c258 100644
--- a/tests/lib_2/async/stream_distinct_test.dart
+++ b/tests/lib_2/async/stream_distinct_test.dart
@@ -66,7 +66,7 @@
       new Stream.fromIterable([1, 1, 2, 2, 1, 3])
           .map((v) => new T(v))
           .distinct()
-          .transform(reifyErrors)
+          .transform(reifyErrors.cast<T, dynamic>())
           .map((v) => v is T ? v.value : "$v"),
       [1, "[2]", "[2]", 3],
       "==-throws");
diff --git a/tests/lib_2/async/timer_not_available_test.dart b/tests/lib_2/async/timer_not_available_test.dart
deleted file mode 100644
index fcbcc13..0000000
--- a/tests/lib_2/async/timer_not_available_test.dart
+++ /dev/null
@@ -1,27 +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 timerNotAvailable;
-
-import 'package:expect/expect.dart';
-import 'dart:async';
-
-main() {
-  final ms = const Duration(milliseconds: 1);
-  bool failed = false;
-  try {
-    new Timer(ms * 5, () {});
-  } on UnsupportedError catch (e) {
-    failed = true;
-  }
-  Expect.isTrue(failed);
-  failed = false;
-  try {
-    var t = new Timer.periodic(ms * 10, (_) {});
-    t.cancel();
-  } on UnsupportedError catch (e) {
-    failed = true;
-  }
-  Expect.isTrue(failed);
-}
diff --git a/tests/lib_2/html/postmessage_anonymous_test.dart b/tests/lib_2/html/postmessage_anonymous_test.dart
new file mode 100644
index 0000000..ab3b1ec
--- /dev/null
+++ b/tests/lib_2/html/postmessage_anonymous_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.
+
+@JS()
+library postmessage_anonymous_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:expect/expect.dart';
+import 'package:js/js.dart';
+
+const String JS_CODE = """
+window.addEventListener('message', handler);
+function handler(e) {
+  var data = e.data;
+  if (typeof data == 'string') return;
+  if (data.recipient != 'JS') return;
+  var response = {recipient: 'DART', msg: data.msg};
+  window.removeEventListener('message', handler);
+  window.postMessage(response, '*');
+}
+""";
+
+const String TEST_MSG = "hello world";
+
+@JS()
+@anonymous
+class Message {
+  external String get recipient;
+  external String get msg;
+  external factory Message({String recipient, String msg});
+}
+
+main() {
+  var subscription;
+  subscription = window.onMessage.listen((e) {
+    var data = e.data;
+    if (data is String) return;
+    if (data['recipient'] != 'DART') return;
+    subscription.cancel();
+    Expect.equals(TEST_MSG, data['msg']);
+  });
+  injectSource(JS_CODE);
+  window.postMessage(Message(recipient: 'JS', msg: TEST_MSG), '*');
+}
+
+void injectSource(String code) {
+  final script = new ScriptElement();
+  script.type = 'text/javascript';
+  script.innerHtml = code;
+  document.body.append(script);
+}
diff --git a/tests/lib_2/lib_2_precompiled.status b/tests/lib_2/lib_2_precompiled.status
index eb79746..5f9922d 100644
--- a/tests/lib_2/lib_2_precompiled.status
+++ b/tests/lib_2/lib_2_precompiled.status
@@ -4,7 +4,6 @@
 
 [ $compiler == none ]
 async/future_or_strong_test: RuntimeError
-async/timer_not_available_test: SkipByDesign # only meant to test when there is no way to implement timer (currently only in d8)
 isolate/compile_time_error_test/01: Skip # Issue 12587
 isolate/ping_test: Skip # Resolve test issues
 mirrors/symbol_validation_test: RuntimeError # Issue 13596
diff --git a/tests/lib_2/mirrors/mirrors_reader_test.dart b/tests/lib_2/mirrors/mirrors_reader_test.dart
index 8717f45..81154d6 100644
--- a/tests/lib_2/mirrors/mirrors_reader_test.dart
+++ b/tests/lib_2/mirrors/mirrors_reader_test.dart
@@ -31,7 +31,7 @@
   }
 
   bool allowUnsupported(var receiver, String tag, UnsupportedError exception) {
-    if (mirrorSystemType == '_LocalMirrorSystem') {
+    if (mirrorSystemType == '_MirrorSystem') {
       // VM mirror system.
       if (tag.endsWith('location')) {
         return receiver is ParameterMirror;
@@ -49,7 +49,7 @@
     // [DeclarationMirror.location] is intentionally not supported in runtime
     // mirrors.
 
-    if (mirrorSystemType == '_LocalMirrorSystem') {
+    if (mirrorSystemType == '_MirrorSystem') {
       // VM mirror system.
     } else if (mirrorSystemType == 'JsMirrorSystem') {
       // Dart2js runtime mirror system.
diff --git a/tests/lib_2/mirrors/parameter_abstract_test.dart b/tests/lib_2/mirrors/parameter_abstract_test.dart
index 298f5e9..252d9e5 100644
--- a/tests/lib_2/mirrors/parameter_abstract_test.dart
+++ b/tests/lib_2/mirrors/parameter_abstract_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// BOGUS: Note that both AST and bytecode modes are missing default values.
-
 import 'dart:mirrors';
 
 import 'package:expect/expect.dart';
@@ -23,12 +21,12 @@
   MethodMirror foo1 = cm.declarations[#foo1];
   expect('Method(s(foo1) in s(C), abstract)', foo1);
   expect(
-      'Parameter(s(x) in s(foo1), optional, named, value = Instance(value = 1), type = Class(s(int) in s(dart.core), top-level))',
+      'Parameter(s(x) in s(foo1), optional, named, type = Class(s(int) in s(dart.core), top-level))',
       foo1.parameters[0]);
   expect(
-      'Parameter(s(y) in s(foo1), optional, named, value = Instance(value = 2), type = Class(s(int) in s(dart.core), top-level))',
+      'Parameter(s(y) in s(foo1), optional, named, type = Class(s(int) in s(dart.core), top-level))',
       foo1.parameters[1]);
   expect(
-      'Parameter(s(z) in s(foo1), optional, named, value = Instance(value = 3), type = Class(s(int) in s(dart.core), top-level))',
+      'Parameter(s(z) in s(foo1), optional, named, type = Class(s(int) in s(dart.core), top-level))',
       foo1.parameters[2]);
 }
diff --git a/tests/lib_2/mirrors/stringify.dart b/tests/lib_2/mirrors/stringify.dart
index b726832..6ff5c3f 100644
--- a/tests/lib_2/mirrors/stringify.dart
+++ b/tests/lib_2/mirrors/stringify.dart
@@ -175,7 +175,7 @@
   throw 'Unexpected value: $value';
 }
 
-expect(expected, actual, [String reason]) {
+expect(expected, actual, [String reason = ""]) {
   Expect.stringEquals(expected, stringify(actual), reason);
 }
 
diff --git a/tests/lib_2/wasm/basic_test.dart b/tests/lib_2/wasm/basic_test.dart
new file mode 100644
index 0000000..34ae182
--- /dev/null
+++ b/tests/lib_2/wasm/basic_test.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.
+
+// Test that we can load a wasm module, find a function, and call it.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  // int64_t square(int64_t n) { return n * n; }
+  var data = Uint8List.fromList([
+    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60,
+    0x01, 0x7e, 0x01, 0x7e, 0x03, 0x02, 0x01, 0x00, 0x04, 0x05, 0x01, 0x70,
+    0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f,
+    0x01, 0x41, 0x80, 0x88, 0x04, 0x0b, 0x07, 0x13, 0x02, 0x06, 0x6d, 0x65,
+    0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x06, 0x73, 0x71, 0x75, 0x61, 0x72,
+    0x65, 0x00, 0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x00,
+    0x7e, 0x0b,
+  ]);
+
+  var inst = WasmModule(data).instantiate(WasmImports("env")
+    ..addMemory("memory", WasmMemory(256, 1024))
+    ..addGlobal<Int32>("__memory_base", 1024, false));
+  var fn = inst.lookupFunction<Int64 Function(Int64)>("square");
+  int n = fn.call([1234]);
+
+  Expect.equals(1234 * 1234, n);
+}
diff --git a/tests/lib_2/wasm/corrupted_error_test.dart b/tests/lib_2/wasm/corrupted_error_test.dart
new file mode 100644
index 0000000..fcc4085
--- /dev/null
+++ b/tests/lib_2/wasm/corrupted_error_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.
+
+// Test error thrown when the wasm module is corrupted.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  var data = Uint8List.fromList([
+    0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, 0x01, 0x7e, 0x01, 0x7e,
+    0x07, 0x13, 0x02, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00,
+    0x06, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x00, 0x00, 0x00, 0x20, 0x00,
+    0x7e, 0x0b,
+  ]);
+
+  Expect.throwsArgumentError(() => WasmModule(data));
+}
diff --git a/tests/lib_2/wasm/fn_call_error_test.dart b/tests/lib_2/wasm/fn_call_error_test.dart
new file mode 100644
index 0000000..e1d2441
--- /dev/null
+++ b/tests/lib_2/wasm/fn_call_error_test.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.
+
+// Test error thrown when a function is called with the wrong args.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  // int64_t square(int64_t n) { return n * n; }
+  var data = Uint8List.fromList([
+    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60,
+    0x01, 0x7e, 0x01, 0x7e, 0x03, 0x02, 0x01, 0x00, 0x04, 0x05, 0x01, 0x70,
+    0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f,
+    0x01, 0x41, 0x80, 0x88, 0x04, 0x0b, 0x07, 0x13, 0x02, 0x06, 0x6d, 0x65,
+    0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x06, 0x73, 0x71, 0x75, 0x61, 0x72,
+    0x65, 0x00, 0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x00,
+    0x7e, 0x0b,
+  ]);
+
+  var inst = WasmModule(data).instantiate(WasmImports("env")
+    ..addMemory("memory", WasmMemory(256, 1024))
+    ..addGlobal<Int32>("__memory_base", 1024, false));
+  var fn = inst.lookupFunction<Int64 Function(Int64)>("square");
+
+  Expect.throwsArgumentError(() => fn.call([]));
+  Expect.throwsArgumentError(() => fn.call([1, 2, 3]));
+  Expect.throwsArgumentError(() => fn.call([1.23]));
+}
diff --git a/tests/lib_2/wasm/fn_mismatch_error_test.dart b/tests/lib_2/wasm/fn_mismatch_error_test.dart
new file mode 100644
index 0000000..308a829
--- /dev/null
+++ b/tests/lib_2/wasm/fn_mismatch_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.
+
+// Test error thrown when the loaded function can't be found.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  // int64_t square(int64_t n) { return n * n; }
+  var data = Uint8List.fromList([
+    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60,
+    0x01, 0x7e, 0x01, 0x7e, 0x03, 0x02, 0x01, 0x00, 0x04, 0x05, 0x01, 0x70,
+    0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f,
+    0x01, 0x41, 0x80, 0x88, 0x04, 0x0b, 0x07, 0x13, 0x02, 0x06, 0x6d, 0x65,
+    0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x06, 0x73, 0x71, 0x75, 0x61, 0x72,
+    0x65, 0x00, 0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x00,
+    0x7e, 0x0b,
+  ]);
+
+  var inst = WasmModule(data).instantiate(WasmImports("env")
+    ..addMemory("memory", WasmMemory(256, 1024))
+    ..addGlobal<Int32>("__memory_base", 1024, false));
+  Expect.isNotNull(inst.lookupFunction<Int64 Function(Int64)>("square"));
+  Expect.throwsArgumentError(
+      () => inst.lookupFunction<Int64 Function(Int64)>("blah"));
+  Expect.throwsArgumentError(
+      () => inst.lookupFunction<Int64 Function()>("square"));
+  Expect.throwsArgumentError(
+      () => inst.lookupFunction<Int64 Function(Int64, Int64)>("square"));
+  Expect.throwsArgumentError(
+      () => inst.lookupFunction<Void Function(Int64)>("square"));
+  Expect.throwsArgumentError(
+      () => inst.lookupFunction<Void Function(dynamic)>("square"));
+}
diff --git a/tests/lib_2/wasm/numerics_test.dart b/tests/lib_2/wasm/numerics_test.dart
new file mode 100644
index 0000000..1d7a199
--- /dev/null
+++ b/tests/lib_2/wasm/numerics_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.
+
+// Test numeric types.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  // int64_t addI64(int64_t x, int64_t y) { return x + y; }
+  // int32_t addI32(int32_t x, int32_t y) { return x + y; }
+  // double addF64(double x, double y) { return x + y; }
+  // float addF32(float x, float y) { return x + y; }
+  var data = Uint8List.fromList([
+    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x19, 0x04, 0x60,
+    0x02, 0x7e, 0x7e, 0x01, 0x7e, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x60,
+    0x02, 0x7c, 0x7c, 0x01, 0x7c, 0x60, 0x02, 0x7d, 0x7d, 0x01, 0x7d, 0x03,
+    0x05, 0x04, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x01, 0x70, 0x01, 0x01,
+    0x01, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f, 0x01, 0x41,
+    0x80, 0x88, 0x04, 0x0b, 0x07, 0x2e, 0x05, 0x06, 0x6d, 0x65, 0x6d, 0x6f,
+    0x72, 0x79, 0x02, 0x00, 0x06, 0x61, 0x64, 0x64, 0x49, 0x36, 0x34, 0x00,
+    0x00, 0x06, 0x61, 0x64, 0x64, 0x49, 0x33, 0x32, 0x00, 0x01, 0x06, 0x61,
+    0x64, 0x64, 0x46, 0x36, 0x34, 0x00, 0x02, 0x06, 0x61, 0x64, 0x64, 0x46,
+    0x33, 0x32, 0x00, 0x03, 0x0a, 0x21, 0x04, 0x07, 0x00, 0x20, 0x01, 0x20,
+    0x00, 0x7c, 0x0b, 0x07, 0x00, 0x20, 0x01, 0x20, 0x00, 0x6a, 0x0b, 0x07,
+    0x00, 0x20, 0x00, 0x20, 0x01, 0xa0, 0x0b, 0x07, 0x00, 0x20, 0x00, 0x20,
+    0x01, 0x92, 0x0b,
+  ]);
+
+  var inst = WasmModule(data).instantiate(WasmImports("env")
+    ..addMemory("memory", WasmMemory(256, 1024))
+    ..addGlobal<Int32>("__memory_base", 1024, false));
+  var addI64 = inst.lookupFunction<Int64 Function(Int64, Int64)>("addI64");
+  var addI32 = inst.lookupFunction<Int32 Function(Int32, Int32)>("addI32");
+  var addF64 = inst.lookupFunction<Double Function(Double, Double)>("addF64");
+  var addF32 = inst.lookupFunction<Float Function(Float, Float)>("addF32");
+
+  int i64 = addI64.call([0x123456789ABCDEF, 0xFEDCBA987654321]);
+  Expect.equals(0x1111111111111110, i64);
+
+  int i32 = addI32.call([0xABCDEF, 0xFEDCBA]);
+  Expect.equals(0x1aaaaa9, i32);
+
+  double f64 = addF64.call([1234.5678, 8765.4321]);
+  Expect.approxEquals(9999.9999, f64, 1e-6);
+
+  double f32 = addF32.call([1234.5678, 8765.4321]);
+  Expect.approxEquals(9999.9999, f32, 1e-3);
+}
diff --git a/tests/lib_2/wasm/void_test.dart b/tests/lib_2/wasm/void_test.dart
new file mode 100644
index 0000000..c2f0707
--- /dev/null
+++ b/tests/lib_2/wasm/void_test.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.
+
+// Test functions with void return type, and functions that take no args.
+
+import "package:expect/expect.dart";
+import "dart:wasm";
+import "dart:typed_data";
+
+void main() {
+  // int64_t x = 0;
+  // void set(int64_t a, int64_t b) { x = a + b; }
+  // int64_t get() { return x; }
+  var data = Uint8List.fromList([
+    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x02, 0x60,
+    0x02, 0x7e, 0x7e, 0x00, 0x60, 0x00, 0x01, 0x7e, 0x03, 0x03, 0x02, 0x00,
+    0x01, 0x04, 0x05, 0x01, 0x70, 0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00,
+    0x02, 0x06, 0x08, 0x01, 0x7f, 0x01, 0x41, 0x90, 0x88, 0x04, 0x0b, 0x07,
+    0x16, 0x03, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x03,
+    0x73, 0x65, 0x74, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, 0x01, 0x0a,
+    0x1e, 0x02, 0x10, 0x00, 0x41, 0x00, 0x20, 0x01, 0x20, 0x00, 0x7c, 0x37,
+    0x03, 0x80, 0x88, 0x80, 0x80, 0x00, 0x0b, 0x0b, 0x00, 0x41, 0x00, 0x29,
+    0x03, 0x80, 0x88, 0x80, 0x80, 0x00, 0x0b, 0x0b, 0x0f, 0x01, 0x00, 0x41,
+    0x80, 0x08, 0x0b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  ]);
+
+  var inst = WasmModule(data).instantiate(WasmImports("env")
+    ..addMemory("memory", WasmMemory(256, 1024))
+    ..addGlobal<Int32>("__memory_base", 1024, false));
+  var setFn = inst.lookupFunction<Void Function(Int64, Int64)>("set");
+  var getFn = inst.lookupFunction<Int64 Function()>("get");
+  Expect.isNull(setFn.call([123, 456]));
+  int n = getFn.call([]);
+  Expect.equals(123 + 456, n);
+}
diff --git a/tests/modular/nnbd/main.dart b/tests/modular/nnbd/main.dart
new file mode 100644
index 0000000..70b498a
--- /dev/null
+++ b/tests/modular/nnbd/main.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';
+
+void main() {
+  int x = 42;
+  int? y;
+
+  Expect.equals(null, y);
+  Expect.throws(() { x = y!;});
+  Expect.equals(42, x);
+
+  y = 17;
+  x = y!;
+  Expect.equals(17, x);
+}
\ No newline at end of file
diff --git a/tests/modular/nnbd/modules.yaml b/tests/modular/nnbd/modules.yaml
new file mode 100644
index 0000000..9b67253
--- /dev/null
+++ b/tests/modular/nnbd/modules.yaml
@@ -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.
+#
+# NNBD modular test
+dependencies:
+  main: expect
+flags:
+  - non-nullable
\ No newline at end of file
diff --git a/third_party/wasmer/Cargo.toml b/third_party/wasmer/Cargo.toml
index 6253430..9f08f16 100644
--- a/third_party/wasmer/Cargo.toml
+++ b/third_party/wasmer/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "wasmer"
-version = "0.6.0"
+version = "0.7.0"
 
 [lib]
 name = "wasmer"
@@ -8,4 +8,4 @@
 path = "wasmer.rs"
 
 [dependencies]
-wasmer-runtime-c-api = "0.6.0"
+wasmer-runtime-c-api = "0.7.0"
diff --git a/tools/VERSION b/tools/VERSION
index da78ef9..be73740 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -33,7 +33,7 @@
 MAJOR 2
 MINOR 6
 PATCH 0
-PRERELEASE 1
+PRERELEASE 2
 PRERELEASE_PATCH 0
-ABI_VERSION 14
-OLDEST_SUPPORTED_ABI_VERSION 13
+ABI_VERSION 16
+OLDEST_SUPPORTED_ABI_VERSION 16
diff --git a/tools/bots/flutter/compile_flutter.sh b/tools/bots/flutter/compile_flutter.sh
index 1c81fba..b86d351 100755
--- a/tools/bots/flutter/compile_flutter.sh
+++ b/tools/bots/flutter/compile_flutter.sh
@@ -30,8 +30,8 @@
 popd
 
 # Directly in temp directory again.
-mkdir engine
-pushd engine
+mkdir src
+pushd src
 git clone -vv --depth 1 https://chromium.googlesource.com/external/github.com/flutter/engine flutter
 mkdir third_party
 pushd third_party
@@ -39,10 +39,12 @@
 popd
 popd
 
+./src/third_party/dart/tools/patches/flutter-engine/apply.sh || true
+
 mkdir flutter_patched_sdk
 
 $checkout/tools/sdks/dart-sdk/bin/dart --packages=$checkout/.packages $checkout/pkg/front_end/tool/_fasta/compile_platform.dart dart:core --single-root-scheme=org-dartlang-sdk --single-root-base=$checkout/ org-dartlang-sdk:///sdk/lib/libraries.json vm_outline_strong.dill vm_platform_strong.dill vm_outline_strong.dill
-$checkout/tools/sdks/dart-sdk/bin/dart --packages=$checkout/.packages $checkout/pkg/front_end/tool/_fasta/compile_platform.dart --target=flutter dart:core --single-root-scheme=org-dartlang-sdk --single-root-base=engine org-dartlang-sdk:///flutter/lib/snapshot/libraries.json vm_outline_strong.dill flutter_patched_sdk/platform_strong.dill flutter_patched_sdk/outline_strong.dill
+$checkout/tools/sdks/dart-sdk/bin/dart --packages=$checkout/.packages $checkout/pkg/front_end/tool/_fasta/compile_platform.dart --target=flutter dart:core --single-root-scheme=org-dartlang-sdk --single-root-base=src org-dartlang-sdk:///flutter/lib/snapshot/libraries.json vm_outline_strong.dill flutter_patched_sdk/platform_strong.dill flutter_patched_sdk/outline_strong.dill
 
 popd
 
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 64de89d..acd6fcf 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -987,6 +987,18 @@
           ]
         },
         {
+          "name": "ddc analyzer modular tests",
+          "script": "out/ReleaseX64/dart-sdk/bin/dart",
+          "testRunner": true,
+          "arguments": [
+            "pkg/dev_compiler/test/modular_ddc_suite.dart",
+            "--configuration-name",
+            "dartdevc-${system}-release",
+            "--verbose",
+            "--use-sdk"
+          ]
+        },
+        {
           "name": "ddc kernel modular tests",
           "script": "out/ReleaseX64/dart-sdk/bin/dart",
           "testRunner": true,
diff --git a/tools/experimental_features.yaml b/tools/experimental_features.yaml
index 495b6d5..dff4c0e 100644
--- a/tools/experimental_features.yaml
+++ b/tools/experimental_features.yaml
@@ -79,6 +79,9 @@
 triple-shift:
   help: "Triple-shift operator"
 
+variance:
+  help: "Sound variance."
+
 #
 # Flags below this line are shipped, retired, or rejected, cannot be specified
 # on the command line, and will eventually be removed.
diff --git a/tools/gn.py b/tools/gn.py
index 908bda9..5cdcc3e 100755
--- a/tools/gn.py
+++ b/tools/gn.py
@@ -408,10 +408,15 @@
     other_group.add_argument(
         '--bytecode',
         '-b',
-        help='Include bytecode in the VMs platform dill',
-        default=False,
+        help='Use bytecode in Dart VM',
+        default=True,
         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/cb80ea7ba9124fd42a34c1d021232113e20d21b1.patch b/tools/patches/flutter-engine/cb80ea7ba9124fd42a34c1d021232113e20d21b1.patch
new file mode 100644
index 0000000..6151279
--- /dev/null
+++ b/tools/patches/flutter-engine/cb80ea7ba9124fd42a34c1d021232113e20d21b1.patch
@@ -0,0 +1,1305 @@
+diff --git a/lib/snapshot/libraries.json b/lib/snapshot/libraries.json
+index b6ffcef58..c4783158b 100644
+--- a/lib/snapshot/libraries.json
++++ b/lib/snapshot/libraries.json
+@@ -4,69 +4,69 @@
+   "flutter": {
+     "libraries": {
+       "_builtin": {
+-        "uri": "../../../third_party/dart/runtime/bin/builtin.dart"
++        "uri": "../../../third_party/dart/sdk/lib/_internal/vm/bin/builtin.dart"
+       },
+       "core": {
+         "patches": [
+-          "../../../third_party/dart/runtime/lib/core_patch.dart",
+-          "../../../third_party/dart/runtime/lib/array.dart",
+-          "../../../third_party/dart/runtime/lib/array_patch.dart",
+-          "../../../third_party/dart/runtime/lib/bigint_patch.dart",
+-          "../../../third_party/dart/runtime/lib/bool_patch.dart",
+-          "../../../third_party/dart/runtime/lib/date_patch.dart",
+-          "../../../third_party/dart/runtime/lib/double.dart",
+-          "../../../third_party/dart/runtime/lib/double_patch.dart",
+-          "../../../third_party/dart/runtime/lib/errors_patch.dart",
+-          "../../../third_party/dart/runtime/lib/expando_patch.dart",
+-          "../../../third_party/dart/runtime/lib/function.dart",
+-          "../../../third_party/dart/runtime/lib/function_patch.dart",
+-          "../../../third_party/dart/runtime/lib/growable_array.dart",
+-          "../../../third_party/dart/runtime/lib/identical_patch.dart",
+-          "../../../third_party/dart/runtime/lib/immutable_map.dart",
+-          "../../../third_party/dart/runtime/lib/integers.dart",
+-          "../../../third_party/dart/runtime/lib/integers_patch.dart",
+-          "../../../third_party/dart/runtime/lib/invocation_mirror_patch.dart",
+-          "../../../third_party/dart/runtime/lib/lib_prefix.dart",
+-          "../../../third_party/dart/runtime/lib/map_patch.dart",
+-          "../../../third_party/dart/runtime/lib/null_patch.dart",
+-          "../../../third_party/dart/runtime/lib/object_patch.dart",
+-          "../../../third_party/dart/runtime/lib/regexp_patch.dart",
+-          "../../../third_party/dart/runtime/lib/stacktrace.dart",
+-          "../../../third_party/dart/runtime/lib/stopwatch_patch.dart",
+-          "../../../third_party/dart/runtime/lib/string_buffer_patch.dart",
+-          "../../../third_party/dart/runtime/lib/string_patch.dart",
+-          "../../../third_party/dart/runtime/lib/type_patch.dart",
+-          "../../../third_party/dart/runtime/lib/uri_patch.dart",
+-          "../../../third_party/dart/runtime/lib/weak_property.dart"
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/core_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/array.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/array_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/bigint_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/bool_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/date_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/double.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/double_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/errors_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/expando_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/function.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/function_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/growable_array.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/identical_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/immutable_map.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/integers.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/integers_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/lib_prefix.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/map_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/null_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/object_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/regexp_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/stacktrace.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/stopwatch_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/string_buffer_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/string_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/type_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/uri_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/weak_property.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/core/core.dart"
+       },
+       "async": {
+         "patches": [
+-          "../../../third_party/dart/runtime/lib/async_patch.dart",
+-          "../../../third_party/dart/runtime/lib/deferred_load_patch.dart",
+-          "../../../third_party/dart/runtime/lib/schedule_microtask_patch.dart",
+-          "../../../third_party/dart/runtime/lib/timer_patch.dart"
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/async_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/deferred_load_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_patch.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/async/async.dart"
+       },
+       "collection": {
+         "patches": [
+-          "../../../third_party/dart/runtime/lib/collection_patch.dart",
+-          "../../../third_party/dart/runtime/lib/compact_hash.dart"
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/collection_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/compact_hash.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/collection/collection.dart"
+       },
+       "ffi": {
+         "patches": [
+-          "../../../third_party/dart/runtime/lib/ffi_dynamic_library_patch.dart",
+-          "../../../third_party/dart/runtime/lib/ffi_native_type_patch.dart",
+-          "../../../third_party/dart/runtime/lib/ffi_patch.dart"
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_patch.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/ffi/ffi.dart"
+       },
+       "typed_data": {
+-        "patches": "../../../third_party/dart/runtime/lib/typed_data_patch.dart",
++        "patches": "../../../third_party/dart/sdk/lib/_internal/vm/lib/typed_data_patch.dart",
+         "uri": "../../../third_party/dart/sdk/lib/typed_data/typed_data.dart"
+       },
+       "nativewrappers": {
+@@ -74,24 +74,24 @@
+       },
+       "mirrors": {
+         "patches": [
+-          "../../../third_party/dart/runtime/lib/mirrors_patch.dart",
+-          "../../../third_party/dart/runtime/lib/mirrors_impl.dart",
+-          "../../../third_party/dart/runtime/lib/mirror_reference.dart"
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_impl.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/mirror_reference.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/mirrors/mirrors.dart"
+       },
+       "developer": {
+         "patches": [
+-          "../../../third_party/dart/runtime/lib/developer.dart",
+-          "../../../third_party/dart/runtime/lib/profiler.dart",
+-          "../../../third_party/dart/runtime/lib/timeline.dart"
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/developer.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/profiler.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/timeline.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/developer/developer.dart"
+       },
+       "isolate": {
+         "patches": [
+-          "../../../third_party/dart/runtime/lib/isolate_patch.dart",
+-          "../../../third_party/dart/runtime/lib/timer_impl.dart"
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/isolate_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_impl.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/isolate/isolate.dart"
+       },
+@@ -100,48 +100,48 @@
+       },
+       "wasm": {
+         "patches": [
+-          "../../../third_party/dart/runtime/lib/wasm_patch.dart"
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/wasm_patch.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/wasm/wasm.dart"
+       },
+       "io": {
+         "patches": [
+-          "../../../third_party/dart/runtime/bin/common_patch.dart",
+-          "../../../third_party/dart/runtime/bin/directory_patch.dart",
+-          "../../../third_party/dart/runtime/bin/eventhandler_patch.dart",
+-          "../../../third_party/dart/runtime/bin/file_patch.dart",
+-          "../../../third_party/dart/runtime/bin/file_system_entity_patch.dart",
+-          "../../../third_party/dart/runtime/bin/filter_patch.dart",
+-          "../../../third_party/dart/runtime/bin/io_service_patch.dart",
+-          "../../../third_party/dart/runtime/bin/namespace_patch.dart",
+-          "../../../third_party/dart/runtime/bin/platform_patch.dart",
+-          "../../../third_party/dart/runtime/bin/process_patch.dart",
+-          "../../../third_party/dart/runtime/bin/socket_patch.dart",
+-          "../../../third_party/dart/runtime/bin/stdio_patch.dart",
+-          "../../../third_party/dart/runtime/bin/secure_socket_patch.dart",
+-          "../../../third_party/dart/runtime/bin/sync_socket_patch.dart"
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/common_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/directory_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/eventhandler_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/file_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/file_system_entity_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/filter_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/io_service_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/namespace_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/platform_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/process_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/socket_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/stdio_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/secure_socket_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/sync_socket_patch.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/io/io.dart"
+       },
+       "_internal": {
+         "patches": [
+-          "../../../third_party/dart/runtime/lib/internal_patch.dart",
+-          "../../../third_party/dart/runtime/lib/class_id_fasta.dart",
+-          "../../../third_party/dart/runtime/lib/print_patch.dart",
+-          "../../../third_party/dart/runtime/lib/symbol_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/internal_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/class_id_fasta.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/print_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/symbol_patch.dart",
+           "../../../third_party/dart/sdk/lib/internal/patch.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/internal/internal.dart"
+       },
+       "convert": {
+-        "patches": "../../../third_party/dart/runtime/lib/convert_patch.dart",
++        "patches": "../../../third_party/dart/sdk/lib/_internal/vm/lib/convert_patch.dart",
+         "uri": "../../../third_party/dart/sdk/lib/convert/convert.dart"
+       },
+       "profiler": {
+         "uri": "../../../third_party/dart/sdk/lib/profiler/profiler.dart"
+       },
+       "math": {
+-        "patches": "../../../third_party/dart/runtime/lib/math_patch.dart",
++        "patches": "../../../third_party/dart/sdk/lib/_internal/vm/lib/math_patch.dart",
+         "uri": "../../../third_party/dart/sdk/lib/math/math.dart"
+       },
+       "_http": {
+diff --git a/lib/snapshot/libraries.yaml b/lib/snapshot/libraries.yaml
+index 392e0500b..7269819f7 100644
+--- a/lib/snapshot/libraries.yaml
++++ b/lib/snapshot/libraries.yaml
+@@ -14,87 +14,87 @@
+ flutter:
+   libraries:
+     _builtin:
+-      uri: "../../../third_party/dart/runtime/bin/builtin.dart"
++      uri: "../../../third_party/dart/sdk/lib/_internal/vm/bin/builtin.dart"
+ 
+     _internal:
+       uri: "../../../third_party/dart/sdk/lib/internal/internal.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/lib/internal_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/class_id_fasta.dart"
+-        - "../../../third_party/dart/runtime/lib/print_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/symbol_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/internal_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/class_id_fasta.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/print_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/symbol_patch.dart"
+         - "../../../third_party/dart/sdk/lib/internal/patch.dart"
+ 
+     async:
+       uri: "../../../third_party/dart/sdk/lib/async/async.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/lib/async_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/deferred_load_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/schedule_microtask_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/timer_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/async_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/deferred_load_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_patch.dart"
+ 
+     collection:
+       uri: "../../../third_party/dart/sdk/lib/collection/collection.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/lib/collection_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/compact_hash.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/collection_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/compact_hash.dart"
+ 
+     convert:
+       uri: "../../../third_party/dart/sdk/lib/convert/convert.dart"
+-      patches: "../../../third_party/dart/runtime/lib/convert_patch.dart"
++      patches: "../../../third_party/dart/sdk/lib/_internal/vm/lib/convert_patch.dart"
+ 
+     core:
+       uri: "../../../third_party/dart/sdk/lib/core/core.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/lib/core_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/array.dart"
+-        - "../../../third_party/dart/runtime/lib/array_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/bigint_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/bool_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/date_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/double.dart"
+-        - "../../../third_party/dart/runtime/lib/double_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/errors_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/expando_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/function.dart"
+-        - "../../../third_party/dart/runtime/lib/function_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/growable_array.dart"
+-        - "../../../third_party/dart/runtime/lib/identical_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/immutable_map.dart"
+-        - "../../../third_party/dart/runtime/lib/integers.dart"
+-        - "../../../third_party/dart/runtime/lib/integers_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/invocation_mirror_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/lib_prefix.dart"
+-        - "../../../third_party/dart/runtime/lib/map_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/null_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/object_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/regexp_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/stacktrace.dart"
+-        - "../../../third_party/dart/runtime/lib/stopwatch_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/string_buffer_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/string_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/type_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/uri_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/weak_property.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/core_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/array.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/array_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/bigint_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/bool_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/date_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/double.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/double_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/errors_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/expando_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/function.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/function_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/growable_array.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/identical_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/immutable_map.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/integers.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/integers_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/lib_prefix.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/map_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/null_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/object_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/regexp_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/stacktrace.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/stopwatch_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/string_buffer_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/string_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/type_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/uri_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/weak_property.dart"
+ 
+     developer:
+       uri: "../../../third_party/dart/sdk/lib/developer/developer.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/lib/developer.dart"
+-        - "../../../third_party/dart/runtime/lib/profiler.dart"
+-        - "../../../third_party/dart/runtime/lib/timeline.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/developer.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/profiler.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/timeline.dart"
+ 
+     ffi:
+       uri: "../../../third_party/dart/sdk/lib/ffi/ffi.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/lib/ffi_dynamic_library_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/ffi_native_type_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/ffi_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_patch.dart"
+ 
+     wasm:
+       uri: "../../../third_party/dart/sdk/lib/wasm/wasm.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/lib/wasm_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/wasm_patch.dart"
+ 
+     _http:
+       uri: "../../../third_party/dart/sdk/lib/_http/http.dart"
+@@ -102,37 +102,37 @@ flutter:
+     io:
+       uri: "../../../third_party/dart/sdk/lib/io/io.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/bin/common_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/directory_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/eventhandler_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/file_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/file_system_entity_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/filter_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/io_service_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/namespace_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/platform_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/process_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/socket_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/stdio_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/secure_socket_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/sync_socket_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/common_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/directory_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/eventhandler_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/file_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/file_system_entity_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/filter_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/io_service_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/namespace_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/platform_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/process_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/socket_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/stdio_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/secure_socket_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/sync_socket_patch.dart"
+ 
+     isolate:
+       uri: "../../../third_party/dart/sdk/lib/isolate/isolate.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/lib/isolate_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/timer_impl.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/isolate_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_impl.dart"
+ 
+     math:
+       uri: "../../../third_party/dart/sdk/lib/math/math.dart"
+-      patches: "../../../third_party/dart/runtime/lib/math_patch.dart"
++      patches: "../../../third_party/dart/sdk/lib/_internal/vm/lib/math_patch.dart"
+ 
+     mirrors:
+       uri: "../../../third_party/dart/sdk/lib/mirrors/mirrors.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/lib/mirrors_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/mirrors_impl.dart"
+-        - "../../../third_party/dart/runtime/lib/mirror_reference.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_impl.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/mirror_reference.dart"
+ 
+     nativewrappers:
+       uri: "../../../third_party/dart/sdk/lib/html/dartium/nativewrappers.dart"
+@@ -142,7 +142,7 @@ flutter:
+ 
+     typed_data:
+       uri: "../../../third_party/dart/sdk/lib/typed_data/typed_data.dart"
+-      patches: "../../../third_party/dart/runtime/lib/typed_data_patch.dart"
++      patches: "../../../third_party/dart/sdk/lib/_internal/vm/lib/typed_data_patch.dart"
+ 
+     ui:
+       uri: "../../lib/ui/ui.dart"
+diff --git a/shell/platform/fuchsia/dart_runner/kernel/libraries.json b/shell/platform/fuchsia/dart_runner/kernel/libraries.json
+index 0abe212e6..24c664852 100644
+--- a/shell/platform/fuchsia/dart_runner/kernel/libraries.json
++++ b/shell/platform/fuchsia/dart_runner/kernel/libraries.json
+@@ -1,43 +1,43 @@
+ {
+   "comment:0": "NOTE: THIS FILE IS GENERATED. DO NOT EDIT.",
+-  "comment:1": "Instead modify 'shell/platform/fuchsia/dart_runner/kernel/libraries.yaml' and follow the instructions therein.",
++  "comment:1": "Instead modify 'flutter/shell/platform/fuchsia/dart_runner/kernel/libraries.yaml' and follow the instructions therein.",
+   "dart_runner": {
+     "libraries": {
+       "_builtin": {
+-        "uri": "../../../../../../third_party/dart/runtime/bin/builtin.dart"
++        "uri": "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/builtin.dart"
+       },
+       "core": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/core_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/array.dart",
+-          "../../../../../../third_party/dart/runtime/lib/array_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/bigint_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/bool_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/date_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/double.dart",
+-          "../../../../../../third_party/dart/runtime/lib/double_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/errors_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/expando_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/function.dart",
+-          "../../../../../../third_party/dart/runtime/lib/function_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/growable_array.dart",
+-          "../../../../../../third_party/dart/runtime/lib/identical_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/immutable_map.dart",
+-          "../../../../../../third_party/dart/runtime/lib/integers.dart",
+-          "../../../../../../third_party/dart/runtime/lib/integers_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/invocation_mirror_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/lib_prefix.dart",
+-          "../../../../../../third_party/dart/runtime/lib/map_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/null_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/object_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/regexp_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/stacktrace.dart",
+-          "../../../../../../third_party/dart/runtime/lib/stopwatch_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/string_buffer_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/string_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/type_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/uri_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/weak_property.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/core_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/array.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/array_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/bigint_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/bool_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/date_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/double.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/double_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/errors_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/expando_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/function.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/function_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/growable_array.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/identical_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/immutable_map.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/integers.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/integers_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/lib_prefix.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/map_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/null_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/object_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/regexp_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/stacktrace.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/stopwatch_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/string_buffer_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/string_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/type_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/uri_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/weak_property.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/core/core.dart"
+       },
+@@ -46,30 +46,30 @@
+       },
+       "async": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/async_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/deferred_load_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/schedule_microtask_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/timer_patch.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/async_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/deferred_load_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/async/async.dart"
+       },
+       "collection": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/collection_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/compact_hash.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/collection_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/compact_hash.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/collection/collection.dart"
+       },
+       "ffi": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/ffi_dynamic_library_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/ffi_native_type_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/ffi_patch.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/ffi/ffi.dart"
+       },
+       "typed_data": {
+-        "patches": "../../../../../../third_party/dart/runtime/lib/typed_data_patch.dart",
++        "patches": "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/typed_data_patch.dart",
+         "uri": "../../../../../../third_party/dart/sdk/lib/typed_data/typed_data.dart"
+       },
+       "nativewrappers": {
+@@ -77,24 +77,24 @@
+       },
+       "mirrors": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/mirrors_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/mirrors_impl.dart",
+-          "../../../../../../third_party/dart/runtime/lib/mirror_reference.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_impl.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirror_reference.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/mirrors/mirrors.dart"
+       },
+       "developer": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/developer.dart",
+-          "../../../../../../third_party/dart/runtime/lib/profiler.dart",
+-          "../../../../../../third_party/dart/runtime/lib/timeline.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/developer.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/profiler.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timeline.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/developer/developer.dart"
+       },
+       "isolate": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/isolate_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/timer_impl.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/isolate_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_impl.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/isolate/isolate.dart"
+       },
+@@ -103,48 +103,48 @@
+       },
+       "wasm": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/wasm_patch.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/wasm_patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/wasm/wasm.dart"
+       },
+       "io": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/bin/common_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/directory_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/eventhandler_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/file_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/file_system_entity_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/filter_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/io_service_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/namespace_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/platform_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/process_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/socket_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/stdio_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/secure_socket_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/sync_socket_patch.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/common_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/directory_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/eventhandler_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/file_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/file_system_entity_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/filter_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/io_service_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/namespace_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/platform_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/process_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/socket_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/stdio_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/secure_socket_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/sync_socket_patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/io/io.dart"
+       },
+       "_internal": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/internal_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/class_id_fasta.dart",
+-          "../../../../../../third_party/dart/runtime/lib/print_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/symbol_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/internal_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/class_id_fasta.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/print_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/symbol_patch.dart",
+           "../../../../../../third_party/dart/sdk/lib/internal/patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/internal/internal.dart"
+       },
+       "convert": {
+-        "patches": "../../../../../../third_party/dart/runtime/lib/convert_patch.dart",
++        "patches": "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/convert_patch.dart",
+         "uri": "../../../../../../third_party/dart/sdk/lib/convert/convert.dart"
+       },
+       "profiler": {
+         "uri": "../../../../../../third_party/dart/sdk/lib/profiler/profiler.dart"
+       },
+       "math": {
+-        "patches": "../../../../../../third_party/dart/runtime/lib/math_patch.dart",
++        "patches": "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/math_patch.dart",
+         "uri": "../../../../../../third_party/dart/sdk/lib/math/math.dart"
+       },
+       "_http": {
+diff --git a/shell/platform/fuchsia/dart_runner/kernel/libraries.yaml b/shell/platform/fuchsia/dart_runner/kernel/libraries.yaml
+index cab901e60..5e1f638cd 100644
+--- a/shell/platform/fuchsia/dart_runner/kernel/libraries.yaml
++++ b/shell/platform/fuchsia/dart_runner/kernel/libraries.yaml
+@@ -14,87 +14,87 @@
+ dart_runner:
+   libraries:
+     _builtin:
+-      uri: "../../../../../../third_party/dart/runtime/bin/builtin.dart"
++      uri: "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/builtin.dart"
+ 
+     _internal:
+       uri: "../../../../../../third_party/dart/sdk/lib/internal/internal.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/internal_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/class_id_fasta.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/print_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/symbol_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/internal_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/class_id_fasta.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/print_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/symbol_patch.dart"
+         - "../../../../../../third_party/dart/sdk/lib/internal/patch.dart"
+ 
+     async:
+       uri: "../../../../../../third_party/dart/sdk/lib/async/async.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/async_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/deferred_load_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/schedule_microtask_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/timer_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/async_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/deferred_load_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_patch.dart"
+ 
+     collection:
+       uri: "../../../../../../third_party/dart/sdk/lib/collection/collection.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/collection_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/compact_hash.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/collection_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/compact_hash.dart"
+ 
+     convert:
+       uri: "../../../../../../third_party/dart/sdk/lib/convert/convert.dart"
+-      patches: "../../../../../../third_party/dart/runtime/lib/convert_patch.dart"
++      patches: "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/convert_patch.dart"
+ 
+     core:
+       uri: "../../../../../../third_party/dart/sdk/lib/core/core.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/core_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/array.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/array_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/bigint_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/bool_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/date_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/double.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/double_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/errors_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/expando_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/function.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/function_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/growable_array.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/identical_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/immutable_map.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/integers.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/integers_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/invocation_mirror_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/lib_prefix.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/map_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/null_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/object_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/regexp_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/stacktrace.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/stopwatch_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/string_buffer_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/string_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/type_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/uri_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/weak_property.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/core_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/array.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/array_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/bigint_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/bool_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/date_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/double.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/double_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/errors_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/expando_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/function.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/function_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/growable_array.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/identical_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/immutable_map.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/integers.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/integers_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/lib_prefix.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/map_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/null_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/object_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/regexp_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/stacktrace.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/stopwatch_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/string_buffer_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/string_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/type_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/uri_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/weak_property.dart"
+ 
+     developer:
+       uri: "../../../../../../third_party/dart/sdk/lib/developer/developer.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/developer.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/profiler.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/timeline.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/developer.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/profiler.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timeline.dart"
+ 
+     ffi:
+       uri: "../../../../../../third_party/dart/sdk/lib/ffi/ffi.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/ffi_dynamic_library_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/ffi_native_type_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/ffi_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_patch.dart"
+ 
+     wasm:
+       uri: "../../../../../../third_party/dart/sdk/lib/wasm/wasm.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/wasm_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/wasm_patch.dart"
+ 
+     _http:
+       uri: "../../../../../../third_party/dart/sdk/lib/_http/http.dart"
+@@ -102,37 +102,37 @@ dart_runner:
+     io:
+       uri: "../../../../../../third_party/dart/sdk/lib/io/io.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/bin/common_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/directory_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/eventhandler_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/file_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/file_system_entity_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/filter_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/io_service_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/namespace_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/platform_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/process_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/socket_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/stdio_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/secure_socket_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/sync_socket_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/common_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/directory_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/eventhandler_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/file_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/file_system_entity_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/filter_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/io_service_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/namespace_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/platform_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/process_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/socket_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/stdio_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/secure_socket_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/sync_socket_patch.dart"
+ 
+     isolate:
+       uri: "../../../../../../third_party/dart/sdk/lib/isolate/isolate.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/isolate_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/timer_impl.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/isolate_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_impl.dart"
+ 
+     math:
+       uri: "../../../../../../third_party/dart/sdk/lib/math/math.dart"
+-      patches: "../../../../../../third_party/dart/runtime/lib/math_patch.dart"
++      patches: "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/math_patch.dart"
+ 
+     mirrors:
+       uri: "../../../../../../third_party/dart/sdk/lib/mirrors/mirrors.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/mirrors_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/mirrors_impl.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/mirror_reference.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_impl.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirror_reference.dart"
+ 
+     nativewrappers:
+       uri: "../../../../../../third_party/dart/sdk/lib/html/dartium/nativewrappers.dart"
+@@ -142,7 +142,7 @@ dart_runner:
+ 
+     typed_data:
+       uri: "../../../../../../third_party/dart/sdk/lib/typed_data/typed_data.dart"
+-      patches: "../../../../../../third_party/dart/runtime/lib/typed_data_patch.dart"
++      patches: "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/typed_data_patch.dart"
+ 
+     fuchsia.builtin:
+       uri: "../../../../../../flutter/shell/platform/fuchsia/dart_runner/embedder/builtin.dart"
+diff --git a/shell/platform/fuchsia/flutter/kernel/libraries.json b/shell/platform/fuchsia/flutter/kernel/libraries.json
+index 5a4602d8c..a8436200f 100644
+--- a/shell/platform/fuchsia/flutter/kernel/libraries.json
++++ b/shell/platform/fuchsia/flutter/kernel/libraries.json
+@@ -1,43 +1,43 @@
+ {
+   "comment:0": "NOTE: THIS FILE IS GENERATED. DO NOT EDIT.",
+-  "comment:1": "Instead modify 'shell/platform/fuchsia/flutter/kernel/libraries.yaml' and follow the instructions therein.",
++  "comment:1": "Instead modify 'flutter/shell/platform/fuchsia/flutter/kernel/libraries.yaml' and follow the instructions therein.",
+   "flutter_runner": {
+     "libraries": {
+       "_builtin": {
+-        "uri": "../../../../../../third_party/dart/runtime/bin/builtin.dart"
++        "uri": "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/builtin.dart"
+       },
+       "core": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/core_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/array.dart",
+-          "../../../../../../third_party/dart/runtime/lib/array_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/bigint_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/bool_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/date_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/double.dart",
+-          "../../../../../../third_party/dart/runtime/lib/double_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/errors_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/expando_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/function.dart",
+-          "../../../../../../third_party/dart/runtime/lib/function_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/growable_array.dart",
+-          "../../../../../../third_party/dart/runtime/lib/identical_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/immutable_map.dart",
+-          "../../../../../../third_party/dart/runtime/lib/integers.dart",
+-          "../../../../../../third_party/dart/runtime/lib/integers_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/invocation_mirror_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/lib_prefix.dart",
+-          "../../../../../../third_party/dart/runtime/lib/map_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/null_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/object_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/regexp_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/stacktrace.dart",
+-          "../../../../../../third_party/dart/runtime/lib/stopwatch_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/string_buffer_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/string_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/type_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/uri_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/weak_property.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/core_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/array.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/array_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/bigint_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/bool_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/date_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/double.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/double_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/errors_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/expando_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/function.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/function_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/growable_array.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/identical_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/immutable_map.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/integers.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/integers_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/lib_prefix.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/map_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/null_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/object_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/regexp_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/stacktrace.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/stopwatch_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/string_buffer_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/string_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/type_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/uri_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/weak_property.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/core/core.dart"
+       },
+@@ -46,30 +46,30 @@
+       },
+       "async": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/async_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/deferred_load_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/schedule_microtask_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/timer_patch.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/async_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/deferred_load_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/async/async.dart"
+       },
+       "collection": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/collection_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/compact_hash.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/collection_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/compact_hash.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/collection/collection.dart"
+       },
+       "ffi": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/ffi_dynamic_library_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/ffi_native_type_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/ffi_patch.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/ffi/ffi.dart"
+       },
+       "typed_data": {
+-        "patches": "../../../../../../third_party/dart/runtime/lib/typed_data_patch.dart",
++        "patches": "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/typed_data_patch.dart",
+         "uri": "../../../../../../third_party/dart/sdk/lib/typed_data/typed_data.dart"
+       },
+       "nativewrappers": {
+@@ -77,24 +77,24 @@
+       },
+       "mirrors": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/mirrors_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/mirrors_impl.dart",
+-          "../../../../../../third_party/dart/runtime/lib/mirror_reference.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_impl.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirror_reference.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/mirrors/mirrors.dart"
+       },
+       "developer": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/developer.dart",
+-          "../../../../../../third_party/dart/runtime/lib/profiler.dart",
+-          "../../../../../../third_party/dart/runtime/lib/timeline.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/developer.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/profiler.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timeline.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/developer/developer.dart"
+       },
+       "isolate": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/isolate_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/timer_impl.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/isolate_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_impl.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/isolate/isolate.dart"
+       },
+@@ -103,48 +103,48 @@
+       },
+       "wasm": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/wasm_patch.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/wasm_patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/wasm/wasm.dart"
+       },
+       "io": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/bin/common_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/directory_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/eventhandler_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/file_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/file_system_entity_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/filter_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/io_service_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/namespace_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/platform_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/process_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/socket_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/stdio_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/secure_socket_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/sync_socket_patch.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/common_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/directory_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/eventhandler_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/file_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/file_system_entity_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/filter_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/io_service_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/namespace_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/platform_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/process_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/socket_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/stdio_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/secure_socket_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/sync_socket_patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/io/io.dart"
+       },
+       "_internal": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/internal_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/class_id_fasta.dart",
+-          "../../../../../../third_party/dart/runtime/lib/print_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/symbol_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/internal_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/class_id_fasta.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/print_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/symbol_patch.dart",
+           "../../../../../../third_party/dart/sdk/lib/internal/patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/internal/internal.dart"
+       },
+       "convert": {
+-        "patches": "../../../../../../third_party/dart/runtime/lib/convert_patch.dart",
++        "patches": "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/convert_patch.dart",
+         "uri": "../../../../../../third_party/dart/sdk/lib/convert/convert.dart"
+       },
+       "profiler": {
+         "uri": "../../../../../../third_party/dart/sdk/lib/profiler/profiler.dart"
+       },
+       "math": {
+-        "patches": "../../../../../../third_party/dart/runtime/lib/math_patch.dart",
++        "patches": "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/math_patch.dart",
+         "uri": "../../../../../../third_party/dart/sdk/lib/math/math.dart"
+       },
+       "_http": {
+@@ -160,7 +160,7 @@
+         "uri": "../../../../../../flutter/lib/ui/ui.dart"
+       },
+       "vmservice_io": {
+-        "uri": "../../../../../../third_party/dart/runtime/bin/vmservice/vmservice_io.dart"
++        "uri": "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/vmservice/vmservice_io.dart"
+       }
+     }
+   }
+diff --git a/shell/platform/fuchsia/flutter/kernel/libraries.yaml b/shell/platform/fuchsia/flutter/kernel/libraries.yaml
+index f8385ca29..05b7f4f9f 100644
+--- a/shell/platform/fuchsia/flutter/kernel/libraries.yaml
++++ b/shell/platform/fuchsia/flutter/kernel/libraries.yaml
+@@ -14,87 +14,87 @@
+ flutter_runner:
+   libraries:
+     _builtin:
+-      uri: "../../../../../../third_party/dart/runtime/bin/builtin.dart"
++      uri: "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/builtin.dart"
+ 
+     _internal:
+       uri: "../../../../../../third_party/dart/sdk/lib/internal/internal.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/internal_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/class_id_fasta.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/print_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/symbol_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/internal_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/class_id_fasta.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/print_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/symbol_patch.dart"
+         - "../../../../../../third_party/dart/sdk/lib/internal/patch.dart"
+ 
+     async:
+       uri: "../../../../../../third_party/dart/sdk/lib/async/async.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/async_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/deferred_load_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/schedule_microtask_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/timer_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/async_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/deferred_load_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_patch.dart"
+ 
+     collection:
+       uri: "../../../../../../third_party/dart/sdk/lib/collection/collection.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/collection_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/compact_hash.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/collection_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/compact_hash.dart"
+ 
+     convert:
+       uri: "../../../../../../third_party/dart/sdk/lib/convert/convert.dart"
+-      patches: "../../../../../../third_party/dart/runtime/lib/convert_patch.dart"
++      patches: "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/convert_patch.dart"
+ 
+     core:
+       uri: "../../../../../../third_party/dart/sdk/lib/core/core.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/core_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/array.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/array_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/bigint_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/bool_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/date_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/double.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/double_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/errors_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/expando_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/function.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/function_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/growable_array.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/identical_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/immutable_map.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/integers.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/integers_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/invocation_mirror_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/lib_prefix.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/map_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/null_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/object_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/regexp_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/stacktrace.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/stopwatch_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/string_buffer_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/string_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/type_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/uri_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/weak_property.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/core_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/array.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/array_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/bigint_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/bool_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/date_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/double.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/double_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/errors_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/expando_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/function.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/function_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/growable_array.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/identical_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/immutable_map.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/integers.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/integers_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/lib_prefix.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/map_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/null_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/object_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/regexp_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/stacktrace.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/stopwatch_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/string_buffer_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/string_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/type_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/uri_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/weak_property.dart"
+ 
+     developer:
+       uri: "../../../../../../third_party/dart/sdk/lib/developer/developer.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/developer.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/profiler.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/timeline.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/developer.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/profiler.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timeline.dart"
+ 
+     ffi:
+       uri: "../../../../../../third_party/dart/sdk/lib/ffi/ffi.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/ffi_dynamic_library_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/ffi_native_type_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/ffi_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_patch.dart"
+ 
+     wasm:
+       uri: "../../../../../../third_party/dart/sdk/lib/wasm/wasm.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/wasm_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/wasm_patch.dart"
+ 
+     _http:
+       uri: "../../../../../../third_party/dart/sdk/lib/_http/http.dart"
+@@ -102,37 +102,37 @@ flutter_runner:
+     io:
+       uri: "../../../../../../third_party/dart/sdk/lib/io/io.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/bin/common_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/directory_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/eventhandler_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/file_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/file_system_entity_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/filter_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/io_service_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/namespace_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/platform_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/process_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/socket_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/stdio_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/secure_socket_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/sync_socket_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/common_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/directory_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/eventhandler_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/file_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/file_system_entity_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/filter_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/io_service_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/namespace_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/platform_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/process_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/socket_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/stdio_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/secure_socket_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/sync_socket_patch.dart"
+ 
+     isolate:
+       uri: "../../../../../../third_party/dart/sdk/lib/isolate/isolate.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/isolate_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/timer_impl.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/isolate_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_impl.dart"
+ 
+     math:
+       uri: "../../../../../../third_party/dart/sdk/lib/math/math.dart"
+-      patches: "../../../../../../third_party/dart/runtime/lib/math_patch.dart"
++      patches: "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/math_patch.dart"
+ 
+     mirrors:
+       uri: "../../../../../../third_party/dart/sdk/lib/mirrors/mirrors.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/mirrors_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/mirrors_impl.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/mirror_reference.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_impl.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirror_reference.dart"
+ 
+     nativewrappers:
+       uri: "../../../../../../third_party/dart/sdk/lib/html/dartium/nativewrappers.dart"
+@@ -142,7 +142,7 @@ flutter_runner:
+ 
+     typed_data:
+       uri: "../../../../../../third_party/dart/sdk/lib/typed_data/typed_data.dart"
+-      patches: "../../../../../../third_party/dart/runtime/lib/typed_data_patch.dart"
++      patches: "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/typed_data_patch.dart"
+ 
+     fuchsia.builtin:
+       uri: "../../../../../../flutter/shell/platform/fuchsia/dart_runner/embedder/builtin.dart"
+@@ -160,4 +160,4 @@ flutter_runner:
+       uri: "../../../../../../third_party/dart/sdk/lib/vmservice/vmservice.dart"
+ 
+     vmservice_io:
+-      uri: "../../../../../../third_party/dart/runtime/bin/vmservice/vmservice_io.dart"
++      uri: "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/vmservice/vmservice_io.dart"
diff --git a/tools/patches/flutter-engine/ea969c358e24f71b865d5f720c0c1c8456a53bad.patch b/tools/patches/flutter-engine/ea969c358e24f71b865d5f720c0c1c8456a53bad.patch
new file mode 100644
index 0000000..6151279
--- /dev/null
+++ b/tools/patches/flutter-engine/ea969c358e24f71b865d5f720c0c1c8456a53bad.patch
@@ -0,0 +1,1305 @@
+diff --git a/lib/snapshot/libraries.json b/lib/snapshot/libraries.json
+index b6ffcef58..c4783158b 100644
+--- a/lib/snapshot/libraries.json
++++ b/lib/snapshot/libraries.json
+@@ -4,69 +4,69 @@
+   "flutter": {
+     "libraries": {
+       "_builtin": {
+-        "uri": "../../../third_party/dart/runtime/bin/builtin.dart"
++        "uri": "../../../third_party/dart/sdk/lib/_internal/vm/bin/builtin.dart"
+       },
+       "core": {
+         "patches": [
+-          "../../../third_party/dart/runtime/lib/core_patch.dart",
+-          "../../../third_party/dart/runtime/lib/array.dart",
+-          "../../../third_party/dart/runtime/lib/array_patch.dart",
+-          "../../../third_party/dart/runtime/lib/bigint_patch.dart",
+-          "../../../third_party/dart/runtime/lib/bool_patch.dart",
+-          "../../../third_party/dart/runtime/lib/date_patch.dart",
+-          "../../../third_party/dart/runtime/lib/double.dart",
+-          "../../../third_party/dart/runtime/lib/double_patch.dart",
+-          "../../../third_party/dart/runtime/lib/errors_patch.dart",
+-          "../../../third_party/dart/runtime/lib/expando_patch.dart",
+-          "../../../third_party/dart/runtime/lib/function.dart",
+-          "../../../third_party/dart/runtime/lib/function_patch.dart",
+-          "../../../third_party/dart/runtime/lib/growable_array.dart",
+-          "../../../third_party/dart/runtime/lib/identical_patch.dart",
+-          "../../../third_party/dart/runtime/lib/immutable_map.dart",
+-          "../../../third_party/dart/runtime/lib/integers.dart",
+-          "../../../third_party/dart/runtime/lib/integers_patch.dart",
+-          "../../../third_party/dart/runtime/lib/invocation_mirror_patch.dart",
+-          "../../../third_party/dart/runtime/lib/lib_prefix.dart",
+-          "../../../third_party/dart/runtime/lib/map_patch.dart",
+-          "../../../third_party/dart/runtime/lib/null_patch.dart",
+-          "../../../third_party/dart/runtime/lib/object_patch.dart",
+-          "../../../third_party/dart/runtime/lib/regexp_patch.dart",
+-          "../../../third_party/dart/runtime/lib/stacktrace.dart",
+-          "../../../third_party/dart/runtime/lib/stopwatch_patch.dart",
+-          "../../../third_party/dart/runtime/lib/string_buffer_patch.dart",
+-          "../../../third_party/dart/runtime/lib/string_patch.dart",
+-          "../../../third_party/dart/runtime/lib/type_patch.dart",
+-          "../../../third_party/dart/runtime/lib/uri_patch.dart",
+-          "../../../third_party/dart/runtime/lib/weak_property.dart"
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/core_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/array.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/array_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/bigint_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/bool_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/date_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/double.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/double_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/errors_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/expando_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/function.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/function_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/growable_array.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/identical_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/immutable_map.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/integers.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/integers_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/lib_prefix.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/map_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/null_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/object_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/regexp_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/stacktrace.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/stopwatch_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/string_buffer_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/string_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/type_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/uri_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/weak_property.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/core/core.dart"
+       },
+       "async": {
+         "patches": [
+-          "../../../third_party/dart/runtime/lib/async_patch.dart",
+-          "../../../third_party/dart/runtime/lib/deferred_load_patch.dart",
+-          "../../../third_party/dart/runtime/lib/schedule_microtask_patch.dart",
+-          "../../../third_party/dart/runtime/lib/timer_patch.dart"
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/async_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/deferred_load_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_patch.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/async/async.dart"
+       },
+       "collection": {
+         "patches": [
+-          "../../../third_party/dart/runtime/lib/collection_patch.dart",
+-          "../../../third_party/dart/runtime/lib/compact_hash.dart"
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/collection_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/compact_hash.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/collection/collection.dart"
+       },
+       "ffi": {
+         "patches": [
+-          "../../../third_party/dart/runtime/lib/ffi_dynamic_library_patch.dart",
+-          "../../../third_party/dart/runtime/lib/ffi_native_type_patch.dart",
+-          "../../../third_party/dart/runtime/lib/ffi_patch.dart"
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_patch.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/ffi/ffi.dart"
+       },
+       "typed_data": {
+-        "patches": "../../../third_party/dart/runtime/lib/typed_data_patch.dart",
++        "patches": "../../../third_party/dart/sdk/lib/_internal/vm/lib/typed_data_patch.dart",
+         "uri": "../../../third_party/dart/sdk/lib/typed_data/typed_data.dart"
+       },
+       "nativewrappers": {
+@@ -74,24 +74,24 @@
+       },
+       "mirrors": {
+         "patches": [
+-          "../../../third_party/dart/runtime/lib/mirrors_patch.dart",
+-          "../../../third_party/dart/runtime/lib/mirrors_impl.dart",
+-          "../../../third_party/dart/runtime/lib/mirror_reference.dart"
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_impl.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/mirror_reference.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/mirrors/mirrors.dart"
+       },
+       "developer": {
+         "patches": [
+-          "../../../third_party/dart/runtime/lib/developer.dart",
+-          "../../../third_party/dart/runtime/lib/profiler.dart",
+-          "../../../third_party/dart/runtime/lib/timeline.dart"
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/developer.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/profiler.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/timeline.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/developer/developer.dart"
+       },
+       "isolate": {
+         "patches": [
+-          "../../../third_party/dart/runtime/lib/isolate_patch.dart",
+-          "../../../third_party/dart/runtime/lib/timer_impl.dart"
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/isolate_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_impl.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/isolate/isolate.dart"
+       },
+@@ -100,48 +100,48 @@
+       },
+       "wasm": {
+         "patches": [
+-          "../../../third_party/dart/runtime/lib/wasm_patch.dart"
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/wasm_patch.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/wasm/wasm.dart"
+       },
+       "io": {
+         "patches": [
+-          "../../../third_party/dart/runtime/bin/common_patch.dart",
+-          "../../../third_party/dart/runtime/bin/directory_patch.dart",
+-          "../../../third_party/dart/runtime/bin/eventhandler_patch.dart",
+-          "../../../third_party/dart/runtime/bin/file_patch.dart",
+-          "../../../third_party/dart/runtime/bin/file_system_entity_patch.dart",
+-          "../../../third_party/dart/runtime/bin/filter_patch.dart",
+-          "../../../third_party/dart/runtime/bin/io_service_patch.dart",
+-          "../../../third_party/dart/runtime/bin/namespace_patch.dart",
+-          "../../../third_party/dart/runtime/bin/platform_patch.dart",
+-          "../../../third_party/dart/runtime/bin/process_patch.dart",
+-          "../../../third_party/dart/runtime/bin/socket_patch.dart",
+-          "../../../third_party/dart/runtime/bin/stdio_patch.dart",
+-          "../../../third_party/dart/runtime/bin/secure_socket_patch.dart",
+-          "../../../third_party/dart/runtime/bin/sync_socket_patch.dart"
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/common_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/directory_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/eventhandler_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/file_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/file_system_entity_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/filter_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/io_service_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/namespace_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/platform_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/process_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/socket_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/stdio_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/secure_socket_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/bin/sync_socket_patch.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/io/io.dart"
+       },
+       "_internal": {
+         "patches": [
+-          "../../../third_party/dart/runtime/lib/internal_patch.dart",
+-          "../../../third_party/dart/runtime/lib/class_id_fasta.dart",
+-          "../../../third_party/dart/runtime/lib/print_patch.dart",
+-          "../../../third_party/dart/runtime/lib/symbol_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/internal_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/class_id_fasta.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/print_patch.dart",
++          "../../../third_party/dart/sdk/lib/_internal/vm/lib/symbol_patch.dart",
+           "../../../third_party/dart/sdk/lib/internal/patch.dart"
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/internal/internal.dart"
+       },
+       "convert": {
+-        "patches": "../../../third_party/dart/runtime/lib/convert_patch.dart",
++        "patches": "../../../third_party/dart/sdk/lib/_internal/vm/lib/convert_patch.dart",
+         "uri": "../../../third_party/dart/sdk/lib/convert/convert.dart"
+       },
+       "profiler": {
+         "uri": "../../../third_party/dart/sdk/lib/profiler/profiler.dart"
+       },
+       "math": {
+-        "patches": "../../../third_party/dart/runtime/lib/math_patch.dart",
++        "patches": "../../../third_party/dart/sdk/lib/_internal/vm/lib/math_patch.dart",
+         "uri": "../../../third_party/dart/sdk/lib/math/math.dart"
+       },
+       "_http": {
+diff --git a/lib/snapshot/libraries.yaml b/lib/snapshot/libraries.yaml
+index 392e0500b..7269819f7 100644
+--- a/lib/snapshot/libraries.yaml
++++ b/lib/snapshot/libraries.yaml
+@@ -14,87 +14,87 @@
+ flutter:
+   libraries:
+     _builtin:
+-      uri: "../../../third_party/dart/runtime/bin/builtin.dart"
++      uri: "../../../third_party/dart/sdk/lib/_internal/vm/bin/builtin.dart"
+ 
+     _internal:
+       uri: "../../../third_party/dart/sdk/lib/internal/internal.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/lib/internal_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/class_id_fasta.dart"
+-        - "../../../third_party/dart/runtime/lib/print_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/symbol_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/internal_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/class_id_fasta.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/print_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/symbol_patch.dart"
+         - "../../../third_party/dart/sdk/lib/internal/patch.dart"
+ 
+     async:
+       uri: "../../../third_party/dart/sdk/lib/async/async.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/lib/async_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/deferred_load_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/schedule_microtask_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/timer_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/async_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/deferred_load_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_patch.dart"
+ 
+     collection:
+       uri: "../../../third_party/dart/sdk/lib/collection/collection.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/lib/collection_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/compact_hash.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/collection_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/compact_hash.dart"
+ 
+     convert:
+       uri: "../../../third_party/dart/sdk/lib/convert/convert.dart"
+-      patches: "../../../third_party/dart/runtime/lib/convert_patch.dart"
++      patches: "../../../third_party/dart/sdk/lib/_internal/vm/lib/convert_patch.dart"
+ 
+     core:
+       uri: "../../../third_party/dart/sdk/lib/core/core.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/lib/core_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/array.dart"
+-        - "../../../third_party/dart/runtime/lib/array_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/bigint_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/bool_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/date_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/double.dart"
+-        - "../../../third_party/dart/runtime/lib/double_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/errors_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/expando_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/function.dart"
+-        - "../../../third_party/dart/runtime/lib/function_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/growable_array.dart"
+-        - "../../../third_party/dart/runtime/lib/identical_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/immutable_map.dart"
+-        - "../../../third_party/dart/runtime/lib/integers.dart"
+-        - "../../../third_party/dart/runtime/lib/integers_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/invocation_mirror_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/lib_prefix.dart"
+-        - "../../../third_party/dart/runtime/lib/map_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/null_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/object_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/regexp_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/stacktrace.dart"
+-        - "../../../third_party/dart/runtime/lib/stopwatch_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/string_buffer_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/string_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/type_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/uri_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/weak_property.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/core_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/array.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/array_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/bigint_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/bool_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/date_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/double.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/double_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/errors_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/expando_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/function.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/function_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/growable_array.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/identical_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/immutable_map.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/integers.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/integers_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/lib_prefix.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/map_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/null_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/object_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/regexp_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/stacktrace.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/stopwatch_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/string_buffer_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/string_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/type_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/uri_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/weak_property.dart"
+ 
+     developer:
+       uri: "../../../third_party/dart/sdk/lib/developer/developer.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/lib/developer.dart"
+-        - "../../../third_party/dart/runtime/lib/profiler.dart"
+-        - "../../../third_party/dart/runtime/lib/timeline.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/developer.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/profiler.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/timeline.dart"
+ 
+     ffi:
+       uri: "../../../third_party/dart/sdk/lib/ffi/ffi.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/lib/ffi_dynamic_library_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/ffi_native_type_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/ffi_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_patch.dart"
+ 
+     wasm:
+       uri: "../../../third_party/dart/sdk/lib/wasm/wasm.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/lib/wasm_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/wasm_patch.dart"
+ 
+     _http:
+       uri: "../../../third_party/dart/sdk/lib/_http/http.dart"
+@@ -102,37 +102,37 @@ flutter:
+     io:
+       uri: "../../../third_party/dart/sdk/lib/io/io.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/bin/common_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/directory_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/eventhandler_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/file_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/file_system_entity_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/filter_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/io_service_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/namespace_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/platform_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/process_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/socket_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/stdio_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/secure_socket_patch.dart"
+-        - "../../../third_party/dart/runtime/bin/sync_socket_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/common_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/directory_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/eventhandler_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/file_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/file_system_entity_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/filter_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/io_service_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/namespace_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/platform_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/process_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/socket_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/stdio_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/secure_socket_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/bin/sync_socket_patch.dart"
+ 
+     isolate:
+       uri: "../../../third_party/dart/sdk/lib/isolate/isolate.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/lib/isolate_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/timer_impl.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/isolate_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_impl.dart"
+ 
+     math:
+       uri: "../../../third_party/dart/sdk/lib/math/math.dart"
+-      patches: "../../../third_party/dart/runtime/lib/math_patch.dart"
++      patches: "../../../third_party/dart/sdk/lib/_internal/vm/lib/math_patch.dart"
+ 
+     mirrors:
+       uri: "../../../third_party/dart/sdk/lib/mirrors/mirrors.dart"
+       patches:
+-        - "../../../third_party/dart/runtime/lib/mirrors_patch.dart"
+-        - "../../../third_party/dart/runtime/lib/mirrors_impl.dart"
+-        - "../../../third_party/dart/runtime/lib/mirror_reference.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_patch.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_impl.dart"
++        - "../../../third_party/dart/sdk/lib/_internal/vm/lib/mirror_reference.dart"
+ 
+     nativewrappers:
+       uri: "../../../third_party/dart/sdk/lib/html/dartium/nativewrappers.dart"
+@@ -142,7 +142,7 @@ flutter:
+ 
+     typed_data:
+       uri: "../../../third_party/dart/sdk/lib/typed_data/typed_data.dart"
+-      patches: "../../../third_party/dart/runtime/lib/typed_data_patch.dart"
++      patches: "../../../third_party/dart/sdk/lib/_internal/vm/lib/typed_data_patch.dart"
+ 
+     ui:
+       uri: "../../lib/ui/ui.dart"
+diff --git a/shell/platform/fuchsia/dart_runner/kernel/libraries.json b/shell/platform/fuchsia/dart_runner/kernel/libraries.json
+index 0abe212e6..24c664852 100644
+--- a/shell/platform/fuchsia/dart_runner/kernel/libraries.json
++++ b/shell/platform/fuchsia/dart_runner/kernel/libraries.json
+@@ -1,43 +1,43 @@
+ {
+   "comment:0": "NOTE: THIS FILE IS GENERATED. DO NOT EDIT.",
+-  "comment:1": "Instead modify 'shell/platform/fuchsia/dart_runner/kernel/libraries.yaml' and follow the instructions therein.",
++  "comment:1": "Instead modify 'flutter/shell/platform/fuchsia/dart_runner/kernel/libraries.yaml' and follow the instructions therein.",
+   "dart_runner": {
+     "libraries": {
+       "_builtin": {
+-        "uri": "../../../../../../third_party/dart/runtime/bin/builtin.dart"
++        "uri": "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/builtin.dart"
+       },
+       "core": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/core_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/array.dart",
+-          "../../../../../../third_party/dart/runtime/lib/array_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/bigint_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/bool_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/date_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/double.dart",
+-          "../../../../../../third_party/dart/runtime/lib/double_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/errors_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/expando_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/function.dart",
+-          "../../../../../../third_party/dart/runtime/lib/function_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/growable_array.dart",
+-          "../../../../../../third_party/dart/runtime/lib/identical_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/immutable_map.dart",
+-          "../../../../../../third_party/dart/runtime/lib/integers.dart",
+-          "../../../../../../third_party/dart/runtime/lib/integers_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/invocation_mirror_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/lib_prefix.dart",
+-          "../../../../../../third_party/dart/runtime/lib/map_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/null_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/object_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/regexp_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/stacktrace.dart",
+-          "../../../../../../third_party/dart/runtime/lib/stopwatch_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/string_buffer_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/string_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/type_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/uri_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/weak_property.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/core_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/array.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/array_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/bigint_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/bool_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/date_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/double.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/double_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/errors_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/expando_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/function.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/function_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/growable_array.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/identical_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/immutable_map.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/integers.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/integers_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/lib_prefix.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/map_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/null_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/object_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/regexp_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/stacktrace.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/stopwatch_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/string_buffer_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/string_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/type_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/uri_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/weak_property.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/core/core.dart"
+       },
+@@ -46,30 +46,30 @@
+       },
+       "async": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/async_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/deferred_load_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/schedule_microtask_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/timer_patch.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/async_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/deferred_load_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/async/async.dart"
+       },
+       "collection": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/collection_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/compact_hash.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/collection_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/compact_hash.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/collection/collection.dart"
+       },
+       "ffi": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/ffi_dynamic_library_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/ffi_native_type_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/ffi_patch.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/ffi/ffi.dart"
+       },
+       "typed_data": {
+-        "patches": "../../../../../../third_party/dart/runtime/lib/typed_data_patch.dart",
++        "patches": "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/typed_data_patch.dart",
+         "uri": "../../../../../../third_party/dart/sdk/lib/typed_data/typed_data.dart"
+       },
+       "nativewrappers": {
+@@ -77,24 +77,24 @@
+       },
+       "mirrors": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/mirrors_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/mirrors_impl.dart",
+-          "../../../../../../third_party/dart/runtime/lib/mirror_reference.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_impl.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirror_reference.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/mirrors/mirrors.dart"
+       },
+       "developer": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/developer.dart",
+-          "../../../../../../third_party/dart/runtime/lib/profiler.dart",
+-          "../../../../../../third_party/dart/runtime/lib/timeline.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/developer.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/profiler.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timeline.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/developer/developer.dart"
+       },
+       "isolate": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/isolate_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/timer_impl.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/isolate_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_impl.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/isolate/isolate.dart"
+       },
+@@ -103,48 +103,48 @@
+       },
+       "wasm": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/wasm_patch.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/wasm_patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/wasm/wasm.dart"
+       },
+       "io": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/bin/common_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/directory_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/eventhandler_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/file_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/file_system_entity_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/filter_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/io_service_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/namespace_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/platform_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/process_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/socket_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/stdio_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/secure_socket_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/sync_socket_patch.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/common_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/directory_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/eventhandler_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/file_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/file_system_entity_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/filter_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/io_service_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/namespace_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/platform_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/process_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/socket_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/stdio_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/secure_socket_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/sync_socket_patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/io/io.dart"
+       },
+       "_internal": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/internal_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/class_id_fasta.dart",
+-          "../../../../../../third_party/dart/runtime/lib/print_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/symbol_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/internal_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/class_id_fasta.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/print_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/symbol_patch.dart",
+           "../../../../../../third_party/dart/sdk/lib/internal/patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/internal/internal.dart"
+       },
+       "convert": {
+-        "patches": "../../../../../../third_party/dart/runtime/lib/convert_patch.dart",
++        "patches": "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/convert_patch.dart",
+         "uri": "../../../../../../third_party/dart/sdk/lib/convert/convert.dart"
+       },
+       "profiler": {
+         "uri": "../../../../../../third_party/dart/sdk/lib/profiler/profiler.dart"
+       },
+       "math": {
+-        "patches": "../../../../../../third_party/dart/runtime/lib/math_patch.dart",
++        "patches": "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/math_patch.dart",
+         "uri": "../../../../../../third_party/dart/sdk/lib/math/math.dart"
+       },
+       "_http": {
+diff --git a/shell/platform/fuchsia/dart_runner/kernel/libraries.yaml b/shell/platform/fuchsia/dart_runner/kernel/libraries.yaml
+index cab901e60..5e1f638cd 100644
+--- a/shell/platform/fuchsia/dart_runner/kernel/libraries.yaml
++++ b/shell/platform/fuchsia/dart_runner/kernel/libraries.yaml
+@@ -14,87 +14,87 @@
+ dart_runner:
+   libraries:
+     _builtin:
+-      uri: "../../../../../../third_party/dart/runtime/bin/builtin.dart"
++      uri: "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/builtin.dart"
+ 
+     _internal:
+       uri: "../../../../../../third_party/dart/sdk/lib/internal/internal.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/internal_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/class_id_fasta.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/print_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/symbol_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/internal_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/class_id_fasta.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/print_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/symbol_patch.dart"
+         - "../../../../../../third_party/dart/sdk/lib/internal/patch.dart"
+ 
+     async:
+       uri: "../../../../../../third_party/dart/sdk/lib/async/async.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/async_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/deferred_load_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/schedule_microtask_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/timer_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/async_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/deferred_load_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_patch.dart"
+ 
+     collection:
+       uri: "../../../../../../third_party/dart/sdk/lib/collection/collection.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/collection_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/compact_hash.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/collection_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/compact_hash.dart"
+ 
+     convert:
+       uri: "../../../../../../third_party/dart/sdk/lib/convert/convert.dart"
+-      patches: "../../../../../../third_party/dart/runtime/lib/convert_patch.dart"
++      patches: "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/convert_patch.dart"
+ 
+     core:
+       uri: "../../../../../../third_party/dart/sdk/lib/core/core.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/core_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/array.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/array_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/bigint_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/bool_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/date_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/double.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/double_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/errors_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/expando_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/function.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/function_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/growable_array.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/identical_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/immutable_map.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/integers.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/integers_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/invocation_mirror_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/lib_prefix.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/map_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/null_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/object_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/regexp_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/stacktrace.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/stopwatch_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/string_buffer_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/string_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/type_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/uri_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/weak_property.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/core_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/array.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/array_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/bigint_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/bool_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/date_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/double.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/double_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/errors_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/expando_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/function.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/function_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/growable_array.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/identical_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/immutable_map.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/integers.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/integers_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/lib_prefix.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/map_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/null_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/object_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/regexp_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/stacktrace.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/stopwatch_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/string_buffer_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/string_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/type_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/uri_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/weak_property.dart"
+ 
+     developer:
+       uri: "../../../../../../third_party/dart/sdk/lib/developer/developer.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/developer.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/profiler.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/timeline.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/developer.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/profiler.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timeline.dart"
+ 
+     ffi:
+       uri: "../../../../../../third_party/dart/sdk/lib/ffi/ffi.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/ffi_dynamic_library_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/ffi_native_type_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/ffi_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_patch.dart"
+ 
+     wasm:
+       uri: "../../../../../../third_party/dart/sdk/lib/wasm/wasm.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/wasm_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/wasm_patch.dart"
+ 
+     _http:
+       uri: "../../../../../../third_party/dart/sdk/lib/_http/http.dart"
+@@ -102,37 +102,37 @@ dart_runner:
+     io:
+       uri: "../../../../../../third_party/dart/sdk/lib/io/io.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/bin/common_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/directory_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/eventhandler_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/file_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/file_system_entity_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/filter_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/io_service_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/namespace_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/platform_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/process_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/socket_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/stdio_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/secure_socket_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/sync_socket_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/common_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/directory_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/eventhandler_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/file_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/file_system_entity_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/filter_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/io_service_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/namespace_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/platform_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/process_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/socket_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/stdio_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/secure_socket_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/sync_socket_patch.dart"
+ 
+     isolate:
+       uri: "../../../../../../third_party/dart/sdk/lib/isolate/isolate.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/isolate_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/timer_impl.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/isolate_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_impl.dart"
+ 
+     math:
+       uri: "../../../../../../third_party/dart/sdk/lib/math/math.dart"
+-      patches: "../../../../../../third_party/dart/runtime/lib/math_patch.dart"
++      patches: "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/math_patch.dart"
+ 
+     mirrors:
+       uri: "../../../../../../third_party/dart/sdk/lib/mirrors/mirrors.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/mirrors_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/mirrors_impl.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/mirror_reference.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_impl.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirror_reference.dart"
+ 
+     nativewrappers:
+       uri: "../../../../../../third_party/dart/sdk/lib/html/dartium/nativewrappers.dart"
+@@ -142,7 +142,7 @@ dart_runner:
+ 
+     typed_data:
+       uri: "../../../../../../third_party/dart/sdk/lib/typed_data/typed_data.dart"
+-      patches: "../../../../../../third_party/dart/runtime/lib/typed_data_patch.dart"
++      patches: "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/typed_data_patch.dart"
+ 
+     fuchsia.builtin:
+       uri: "../../../../../../flutter/shell/platform/fuchsia/dart_runner/embedder/builtin.dart"
+diff --git a/shell/platform/fuchsia/flutter/kernel/libraries.json b/shell/platform/fuchsia/flutter/kernel/libraries.json
+index 5a4602d8c..a8436200f 100644
+--- a/shell/platform/fuchsia/flutter/kernel/libraries.json
++++ b/shell/platform/fuchsia/flutter/kernel/libraries.json
+@@ -1,43 +1,43 @@
+ {
+   "comment:0": "NOTE: THIS FILE IS GENERATED. DO NOT EDIT.",
+-  "comment:1": "Instead modify 'shell/platform/fuchsia/flutter/kernel/libraries.yaml' and follow the instructions therein.",
++  "comment:1": "Instead modify 'flutter/shell/platform/fuchsia/flutter/kernel/libraries.yaml' and follow the instructions therein.",
+   "flutter_runner": {
+     "libraries": {
+       "_builtin": {
+-        "uri": "../../../../../../third_party/dart/runtime/bin/builtin.dart"
++        "uri": "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/builtin.dart"
+       },
+       "core": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/core_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/array.dart",
+-          "../../../../../../third_party/dart/runtime/lib/array_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/bigint_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/bool_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/date_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/double.dart",
+-          "../../../../../../third_party/dart/runtime/lib/double_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/errors_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/expando_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/function.dart",
+-          "../../../../../../third_party/dart/runtime/lib/function_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/growable_array.dart",
+-          "../../../../../../third_party/dart/runtime/lib/identical_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/immutable_map.dart",
+-          "../../../../../../third_party/dart/runtime/lib/integers.dart",
+-          "../../../../../../third_party/dart/runtime/lib/integers_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/invocation_mirror_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/lib_prefix.dart",
+-          "../../../../../../third_party/dart/runtime/lib/map_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/null_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/object_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/regexp_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/stacktrace.dart",
+-          "../../../../../../third_party/dart/runtime/lib/stopwatch_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/string_buffer_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/string_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/type_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/uri_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/weak_property.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/core_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/array.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/array_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/bigint_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/bool_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/date_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/double.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/double_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/errors_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/expando_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/function.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/function_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/growable_array.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/identical_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/immutable_map.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/integers.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/integers_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/lib_prefix.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/map_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/null_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/object_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/regexp_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/stacktrace.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/stopwatch_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/string_buffer_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/string_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/type_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/uri_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/weak_property.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/core/core.dart"
+       },
+@@ -46,30 +46,30 @@
+       },
+       "async": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/async_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/deferred_load_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/schedule_microtask_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/timer_patch.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/async_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/deferred_load_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/async/async.dart"
+       },
+       "collection": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/collection_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/compact_hash.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/collection_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/compact_hash.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/collection/collection.dart"
+       },
+       "ffi": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/ffi_dynamic_library_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/ffi_native_type_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/ffi_patch.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/ffi/ffi.dart"
+       },
+       "typed_data": {
+-        "patches": "../../../../../../third_party/dart/runtime/lib/typed_data_patch.dart",
++        "patches": "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/typed_data_patch.dart",
+         "uri": "../../../../../../third_party/dart/sdk/lib/typed_data/typed_data.dart"
+       },
+       "nativewrappers": {
+@@ -77,24 +77,24 @@
+       },
+       "mirrors": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/mirrors_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/mirrors_impl.dart",
+-          "../../../../../../third_party/dart/runtime/lib/mirror_reference.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_impl.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirror_reference.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/mirrors/mirrors.dart"
+       },
+       "developer": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/developer.dart",
+-          "../../../../../../third_party/dart/runtime/lib/profiler.dart",
+-          "../../../../../../third_party/dart/runtime/lib/timeline.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/developer.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/profiler.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timeline.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/developer/developer.dart"
+       },
+       "isolate": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/isolate_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/timer_impl.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/isolate_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_impl.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/isolate/isolate.dart"
+       },
+@@ -103,48 +103,48 @@
+       },
+       "wasm": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/wasm_patch.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/wasm_patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/wasm/wasm.dart"
+       },
+       "io": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/bin/common_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/directory_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/eventhandler_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/file_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/file_system_entity_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/filter_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/io_service_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/namespace_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/platform_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/process_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/socket_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/stdio_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/secure_socket_patch.dart",
+-          "../../../../../../third_party/dart/runtime/bin/sync_socket_patch.dart"
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/common_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/directory_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/eventhandler_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/file_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/file_system_entity_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/filter_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/io_service_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/namespace_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/platform_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/process_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/socket_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/stdio_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/secure_socket_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/sync_socket_patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/io/io.dart"
+       },
+       "_internal": {
+         "patches": [
+-          "../../../../../../third_party/dart/runtime/lib/internal_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/class_id_fasta.dart",
+-          "../../../../../../third_party/dart/runtime/lib/print_patch.dart",
+-          "../../../../../../third_party/dart/runtime/lib/symbol_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/internal_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/class_id_fasta.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/print_patch.dart",
++          "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/symbol_patch.dart",
+           "../../../../../../third_party/dart/sdk/lib/internal/patch.dart"
+         ],
+         "uri": "../../../../../../third_party/dart/sdk/lib/internal/internal.dart"
+       },
+       "convert": {
+-        "patches": "../../../../../../third_party/dart/runtime/lib/convert_patch.dart",
++        "patches": "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/convert_patch.dart",
+         "uri": "../../../../../../third_party/dart/sdk/lib/convert/convert.dart"
+       },
+       "profiler": {
+         "uri": "../../../../../../third_party/dart/sdk/lib/profiler/profiler.dart"
+       },
+       "math": {
+-        "patches": "../../../../../../third_party/dart/runtime/lib/math_patch.dart",
++        "patches": "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/math_patch.dart",
+         "uri": "../../../../../../third_party/dart/sdk/lib/math/math.dart"
+       },
+       "_http": {
+@@ -160,7 +160,7 @@
+         "uri": "../../../../../../flutter/lib/ui/ui.dart"
+       },
+       "vmservice_io": {
+-        "uri": "../../../../../../third_party/dart/runtime/bin/vmservice/vmservice_io.dart"
++        "uri": "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/vmservice/vmservice_io.dart"
+       }
+     }
+   }
+diff --git a/shell/platform/fuchsia/flutter/kernel/libraries.yaml b/shell/platform/fuchsia/flutter/kernel/libraries.yaml
+index f8385ca29..05b7f4f9f 100644
+--- a/shell/platform/fuchsia/flutter/kernel/libraries.yaml
++++ b/shell/platform/fuchsia/flutter/kernel/libraries.yaml
+@@ -14,87 +14,87 @@
+ flutter_runner:
+   libraries:
+     _builtin:
+-      uri: "../../../../../../third_party/dart/runtime/bin/builtin.dart"
++      uri: "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/builtin.dart"
+ 
+     _internal:
+       uri: "../../../../../../third_party/dart/sdk/lib/internal/internal.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/internal_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/class_id_fasta.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/print_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/symbol_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/internal_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/class_id_fasta.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/print_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/symbol_patch.dart"
+         - "../../../../../../third_party/dart/sdk/lib/internal/patch.dart"
+ 
+     async:
+       uri: "../../../../../../third_party/dart/sdk/lib/async/async.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/async_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/deferred_load_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/schedule_microtask_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/timer_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/async_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/deferred_load_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_patch.dart"
+ 
+     collection:
+       uri: "../../../../../../third_party/dart/sdk/lib/collection/collection.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/collection_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/compact_hash.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/collection_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/compact_hash.dart"
+ 
+     convert:
+       uri: "../../../../../../third_party/dart/sdk/lib/convert/convert.dart"
+-      patches: "../../../../../../third_party/dart/runtime/lib/convert_patch.dart"
++      patches: "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/convert_patch.dart"
+ 
+     core:
+       uri: "../../../../../../third_party/dart/sdk/lib/core/core.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/core_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/array.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/array_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/bigint_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/bool_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/date_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/double.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/double_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/errors_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/expando_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/function.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/function_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/growable_array.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/identical_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/immutable_map.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/integers.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/integers_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/invocation_mirror_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/lib_prefix.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/map_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/null_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/object_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/regexp_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/stacktrace.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/stopwatch_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/string_buffer_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/string_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/type_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/uri_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/weak_property.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/core_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/array.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/array_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/bigint_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/bool_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/date_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/double.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/double_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/errors_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/expando_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/function.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/function_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/growable_array.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/identical_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/immutable_map.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/integers.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/integers_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/lib_prefix.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/map_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/null_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/object_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/regexp_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/stacktrace.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/stopwatch_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/string_buffer_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/string_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/type_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/uri_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/weak_property.dart"
+ 
+     developer:
+       uri: "../../../../../../third_party/dart/sdk/lib/developer/developer.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/developer.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/profiler.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/timeline.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/developer.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/profiler.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timeline.dart"
+ 
+     ffi:
+       uri: "../../../../../../third_party/dart/sdk/lib/ffi/ffi.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/ffi_dynamic_library_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/ffi_native_type_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/ffi_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_patch.dart"
+ 
+     wasm:
+       uri: "../../../../../../third_party/dart/sdk/lib/wasm/wasm.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/wasm_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/wasm_patch.dart"
+ 
+     _http:
+       uri: "../../../../../../third_party/dart/sdk/lib/_http/http.dart"
+@@ -102,37 +102,37 @@ flutter_runner:
+     io:
+       uri: "../../../../../../third_party/dart/sdk/lib/io/io.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/bin/common_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/directory_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/eventhandler_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/file_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/file_system_entity_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/filter_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/io_service_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/namespace_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/platform_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/process_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/socket_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/stdio_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/secure_socket_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/bin/sync_socket_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/common_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/directory_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/eventhandler_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/file_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/file_system_entity_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/filter_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/io_service_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/namespace_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/platform_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/process_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/socket_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/stdio_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/secure_socket_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/sync_socket_patch.dart"
+ 
+     isolate:
+       uri: "../../../../../../third_party/dart/sdk/lib/isolate/isolate.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/isolate_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/timer_impl.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/isolate_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/timer_impl.dart"
+ 
+     math:
+       uri: "../../../../../../third_party/dart/sdk/lib/math/math.dart"
+-      patches: "../../../../../../third_party/dart/runtime/lib/math_patch.dart"
++      patches: "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/math_patch.dart"
+ 
+     mirrors:
+       uri: "../../../../../../third_party/dart/sdk/lib/mirrors/mirrors.dart"
+       patches:
+-        - "../../../../../../third_party/dart/runtime/lib/mirrors_patch.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/mirrors_impl.dart"
+-        - "../../../../../../third_party/dart/runtime/lib/mirror_reference.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_patch.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirrors_impl.dart"
++        - "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/mirror_reference.dart"
+ 
+     nativewrappers:
+       uri: "../../../../../../third_party/dart/sdk/lib/html/dartium/nativewrappers.dart"
+@@ -142,7 +142,7 @@ flutter_runner:
+ 
+     typed_data:
+       uri: "../../../../../../third_party/dart/sdk/lib/typed_data/typed_data.dart"
+-      patches: "../../../../../../third_party/dart/runtime/lib/typed_data_patch.dart"
++      patches: "../../../../../../third_party/dart/sdk/lib/_internal/vm/lib/typed_data_patch.dart"
+ 
+     fuchsia.builtin:
+       uri: "../../../../../../flutter/shell/platform/fuchsia/dart_runner/embedder/builtin.dart"
+@@ -160,4 +160,4 @@ flutter_runner:
+       uri: "../../../../../../third_party/dart/sdk/lib/vmservice/vmservice.dart"
+ 
+     vmservice_io:
+-      uri: "../../../../../../third_party/dart/runtime/bin/vmservice/vmservice_io.dart"
++      uri: "../../../../../../third_party/dart/sdk/lib/_internal/vm/bin/vmservice/vmservice_io.dart"
diff --git a/tools/run_abi_tests.py b/tools/run_abi_tests.py
index 4f4f049..e32f008 100644
--- a/tools/run_abi_tests.py
+++ b/tools/run_abi_tests.py
@@ -140,7 +140,7 @@
 def diffResults(results):
     outResult = pickOne(results)
     exp = results[None]['result'] if None in results else None
-    outResult['configuration'] = 'vm-dartkb-linux-release-x64-abi'
+    outResult['configuration'] = 'dartkb-abi-linux-release-x64'
     outResult['expected'] = exp
     outResult['result'] = exp
     outResult['matches'] = True
@@ -163,7 +163,7 @@
     logs = ["%s: %s" % (str(v), l['log']) for v, l in logRecords.items()]
     return {
         'name': result['name'],
-        'configuration': 'vm-dartkb-linux-release-x64-abi',
+        'configuration': 'dartkb-abi-linux-release-x64',
         'result': result['result'],
         'log': '\n\n\n'.join([repr(diffs)] + logs),
     }
diff --git a/utils/application_snapshot.gni b/utils/application_snapshot.gni
index 2c257a2..4356f1c 100644
--- a/utils/application_snapshot.gni
+++ b/utils/application_snapshot.gni
@@ -74,11 +74,62 @@
   if (defined(invoker.output)) {
     output = invoker.output
   }
+
+  # Build the kernel file using the prebuilt VM to speed up the debug and
+  # simulator builds.
+  prebuilt_dart_action(target_name + "_dill") {
+    deps =
+        extra_deps + [
+          "$_dart_root/runtime/vm:kernel_platform_files($dart_host_toolchain)",
+          "$_dart_root/runtime/vm:vm_platform",
+        ]
+    gen_kernel_script = "$_dart_root/pkg/vm/bin/gen_kernel.dart"
+    platform_dill = "$root_out_dir/vm_platform_strong.dill"
+
+    inputs = extra_inputs + [
+               gen_kernel_script,
+               platform_dill,
+               main_dart,
+               dot_packages,
+             ]
+    output = "$target_gen_dir/$name.dart.dill"
+    outputs = [
+      output,
+    ]
+
+    depfile = "$output.d"
+    abs_depfile = rebase_path(depfile)
+    rebased_output = rebase_path(output, root_build_dir)
+    vm_args = [
+      "--depfile=$abs_depfile",
+      "--depfile_output_filename=$rebased_output",
+    ]
+
+    script = gen_kernel_script
+
+    args = [
+      "--packages=" + rebase_path(dot_packages),
+      "--platform=" + rebase_path(platform_dill),
+      "--no-aot",
+      "--no-embed-sources",
+      "--no-link-platform",
+      "--output=" + rebase_path(output),
+    ]
+    if (dart_platform_bytecode) {
+      args += [
+        "--gen-bytecode",
+        "--drop-ast",
+        "--bytecode-options=source-positions",
+      ]
+    }
+    args += [ rebase_path(main_dart) ]
+  }
+
   dart_action(target_name) {
-    deps = extra_deps
+    deps = extra_deps + [ ":${target_name}_dill" ]
     depfile = "$output.d"
 
-    script = main_dart
+    script = "$target_gen_dir/$name.dart.dill"
 
     inputs = extra_inputs
 
@@ -90,16 +141,14 @@
     abs_output = rebase_path(output, root_build_dir)
 
     vm_args = [
-      "--deterministic",
-      "--packages=$dot_packages",
-      "--snapshot=$abs_output",
-      "--snapshot-depfile=$abs_depfile",
-    ] + snapshot_vm_args
+                "--deterministic",
+                "--packages=$dot_packages",
+                "--snapshot=$abs_output",
+                "--snapshot-depfile=$abs_depfile",
+              ] + snapshot_vm_args
 
     if (dart_snapshot_kind == "kernel") {
-      vm_args += [
-        "--snapshot-kind=kernel",
-      ]
+      vm_args += [ "--snapshot-kind=kernel" ]
       assert(training_args != "", "Ignoring unused argument")
       args = []
     } else if (dart_snapshot_kind == "app-jit") {
@@ -141,9 +190,7 @@
     if (!defined(invoker.deps)) {
       deps = []
     }
-    deps += [
-      "$_dart_root/utils/kernel-service:kernel-service"
-    ]
+    deps += [ "$_dart_root/utils/kernel-service:kernel-service" ]
   }
 }
 
diff --git a/utils/bazel/kernel_worker.dart b/utils/bazel/kernel_worker.dart
index d18212b..8662ed1 100644
--- a/utils/bazel/kernel_worker.dart
+++ b/utils/bazel/kernel_worker.dart
@@ -18,7 +18,7 @@
 import 'package:build_integration/file_system/multi_root.dart';
 import 'package:dev_compiler/src/kernel/target.dart';
 import 'package:front_end/src/api_unstable/bazel_worker.dart' as fe;
-import 'package:kernel/ast.dart' show Component, Library;
+import 'package:kernel/ast.dart' show Component, Library, Reference;
 import 'package:kernel/target/targets.dart';
 import 'package:vm/target/vm.dart';
 import 'package:vm/target/flutter.dart';
@@ -337,10 +337,13 @@
         incrementalComponent.problemsAsJson = null;
         incrementalComponent.mainMethod = null;
         target.performOutlineTransformations(incrementalComponent);
+        makeStable(incrementalComponent);
         return Future.value(fe.serializeComponent(incrementalComponent,
             includeSources: false, includeOffsets: false));
       }
 
+      makeStable(incrementalComponent);
+
       return Future.value(fe.serializeComponent(incrementalComponent,
           filter: excludeNonSources
               ? (library) => sources.contains(library.importUri)
@@ -381,6 +384,22 @@
   return new ComputeKernelResult(succeeded, state);
 }
 
+/// Make sure the output is stable by sorting libraries and additional exports.
+void makeStable(Component c) {
+  // Make sure the output is stable.
+  c.libraries.sort((l1, l2) {
+    return "${l1.fileUri}".compareTo("${l2.fileUri}");
+  });
+  c.problemsAsJson?.sort();
+  c.computeCanonicalNames();
+  for (Library library in c.libraries) {
+    library.additionalExports.sort((Reference r1, Reference r2) {
+      return "${r1.canonicalName}".compareTo("${r2.canonicalName}");
+    });
+    library.problemsAsJson?.sort();
+  }
+}
+
 /// Extends the DevCompilerTarget to transform outlines to meet the requirements
 /// of summaries in bazel and package-build.
 ///
diff --git a/utils/compiler/BUILD.gn b/utils/compiler/BUILD.gn
index 07e8087..27dfc69 100644
--- a/utils/compiler/BUILD.gn
+++ b/utils/compiler/BUILD.gn
@@ -3,8 +3,8 @@
 # BSD-style license that can be found in the LICENSE file.
 
 import("../../utils/compile_platform.gni")
-import("../create_timestamp.gni")
 import("../application_snapshot.gni")
+import("../create_timestamp.gni")
 
 create_timestamp_file("dart2js_files_stamp") {
   path = rebase_path("../../pkg/compiler/lib")
@@ -21,18 +21,13 @@
   output = "$target_gen_dir/dartdoc_files.stamp"
 }
 
-dart_action("dart2js_create_snapshot_entry") {
+prebuilt_dart_action("dart2js_create_snapshot_entry") {
   deps = [
     ":dart2js_files_stamp",
     ":dartdoc_files_stamp",
     ":runtime_lib_files_stamp",
   ]
 
-  # dart_action() needs kernel service snapshot to run in Dart 2 mode.
-  # This can't be added as a dependency to dart_action() itself as it will
-  # create a circular dependency.
-  deps += [ "../../utils/kernel-service:kernel-service" ]
-
   output_dir = rebase_path(target_gen_dir)
 
   script = "create_snapshot_entry.dart"
diff --git a/utils/dartdevc/BUILD.gn b/utils/dartdevc/BUILD.gn
index b7b63ce..2048ad4 100644
--- a/utils/dartdevc/BUILD.gn
+++ b/utils/dartdevc/BUILD.gn
@@ -30,7 +30,9 @@
     ":dartdevc_kernel_sdk_outline",
   ]
 
-  inputs = [ sdk_dill ]
+  inputs = [
+    sdk_dill,
+  ]
 }
 
 sdk_lib_files = exec_script("../../tools/list_dart_files.py",
@@ -62,16 +64,11 @@
   abs_main = rebase_path(main)
   abs_output = rebase_path(out)
 
-  dart_action(target_name) {
+  prebuilt_dart_action(target_name) {
     deps = [
       "../compiler:compile_dart2js_platform",
     ]
 
-    # dart_action() needs kernel service snapshot to run in Dart 2 mode.
-    # This can't be added as a dependency to dart_action() itself as it will
-    # create a circular dependency.
-    deps += [ "../../utils/kernel-service:kernel-service" ]
-
     inputs = sdk_lib_files + compiler_files + dev_compiler_files + [
                "$root_out_dir/dart2js_platform.dill",
                "$root_out_dir/dart2js_outline.dill",
@@ -89,6 +86,7 @@
       "-m",
       "-o$abs_output",
       "--no-source-maps",
+      "--platform-binaries=" + rebase_path("$root_out_dir"),
     ]
   }
 }
@@ -211,8 +209,8 @@
 group("dartdevc_test") {
   deps = [
     ":dartdevc",
-    ":dartdevc_sdk",
     ":dartdevc_kernel_sdk",
+    ":dartdevc_sdk",
     ":dartdevc_test_pkg",
     "../../sdk:create_sdk",
   ]
@@ -223,8 +221,8 @@
 # building the Dart VM and create_sdk.
 group("dartdevc_test_local") {
   deps = [
-    ":dartdevc_sdk",
     ":dartdevc_kernel_sdk",
+    ":dartdevc_sdk",
     ":dartdevc_test_pkg",
   ]
 }
@@ -244,10 +242,10 @@
 prebuilt_dart_action("dartdevc_test_pkg") {
   deps = [
     ":dartdevc_files_stamp",
-    ":dartdevc_sdk",
     ":dartdevc_kernel_sdk",
-    ":dartdevc_kernel_sdk_outline",
     ":dartdevc_kernel_sdk_libraries_json",
+    ":dartdevc_kernel_sdk_outline",
+    ":dartdevc_sdk",
     "../../pkg:pkg_files_stamp",
   ]
 
@@ -319,9 +317,9 @@
 
 prebuilt_dart_action("dartdevc_kernel_sdk_outline") {
   deps = [
-    "../../pkg:pkg_files_stamp",
     ":dartdevc_files_stamp",
     ":dartdevc_sdk_patch_stamp",
+    "../../pkg:pkg_files_stamp",
   ]
 
   inputs = [
@@ -349,7 +347,7 @@
     "--output",
     rebase_path(sdk_dill),
     "--source",
-    "dart:core"
+    "dart:core",
   ]
 }
 
@@ -365,9 +363,9 @@
 # Compiles the DDC SDK's kernel summary and JS code.
 prebuilt_dart_action("dartdevc_kernel_sdk") {
   deps = [
-    "../../pkg:pkg_files_stamp",
     ":dartdevc_files_stamp",
     ":dartdevc_sdk_patch_stamp",
+    "../../pkg:pkg_files_stamp",
   ]
 
   inputs = [
diff --git a/utils/kernel-service/BUILD.gn b/utils/kernel-service/BUILD.gn
index 9f926e3..9ed386a 100644
--- a/utils/kernel-service/BUILD.gn
+++ b/utils/kernel-service/BUILD.gn
@@ -10,7 +10,6 @@
 group("kernel-service") {
   if (create_kernel_service_snapshot) {
     deps = [
-      # TODO(rmacnak): Link this into 'dart'.
       ":copy_kernel-service_snapshot",
     ]
   } else {
@@ -20,16 +19,15 @@
   }
 }
 
-# TODO: Switch this to use kernel based app-jit snapshot
-# when we are ready to switch to the kernel based core snapshots.
 kernel_application_snapshot("kernel-service_snapshot") {
-  main_dart = "$root_gen_dir/kernel_service.dill"
-  deps = [
-    ":kernel_service_dill",
-  ]
+  main_dart = "../../pkg/vm/bin/kernel_service.dart"
   training_args = [
     "--train",
-    "file:///" + rebase_path("../../pkg/compiler/lib/src/dart2js.dart"),
+
+    # Force triple-slashes both on Windows and otherwise.
+    # Becomes e.g. file:///full/path/to/file and "file:///C:/full/path/to/file.
+    # Without the ', "/"' part, on Linux it would get four slashes.
+    "file:///" + rebase_path("../../pkg/compiler/lib/src/dart2js.dart", "/"),
   ]
   if (dart_platform_bytecode) {
     training_args += [ "--bytecode" ]
@@ -59,6 +57,7 @@
     "--train",
     "--sdk-root=$sdk_root/",
     "--platform=$sdk_root/vm_platform_strong.dill",
+    rebase_path(main_dart),
   ]
   output = "$root_out_dir/frontend_server.dart.snapshot"
 }
@@ -91,16 +90,26 @@
     ]
 
     script = gen_kernel_script
+    scheme = "org-dartlang-kernel-service"
 
     args =
         invoker.extra_args + [
-          "--packages=" + rebase_path("../../.packages"),
+          "--packages=" + scheme + ":///.packages",
           "--platform=" + rebase_path("$root_out_dir/vm_platform_strong.dill"),
+          "--filesystem-root=" + rebase_path("../../"),
+          "--filesystem-scheme=" + scheme,
           "--no-aot",
           "--no-embed-sources",
           "--output=" + rebase_path(output),
-          rebase_path(kernel_service_script),
+          scheme + ":///pkg/vm/bin/kernel_service.dart",
         ]
+
+    if (dart_platform_bytecode) {
+      args += [
+        "--gen-bytecode",
+        "--drop-ast",
+      ]
+    }
   }
 }